2013-05-16 2 views
4

다음과 같은 문제가 있습니다 : 나는 500mb에 가까운 파일을 가지고 있습니다. 그 텍스트는 모두 한 줄에 있습니다. 텍스트는, 가상 선이 끝나는 그라고 ROW_DEL를 구분하고이 같은 텍스트에 있습니다 :매우 큰 단일 라인 txt 파일을 읽고 그것을 분할하십시오

this is a line ROW_DEL and this is a line 

지금 나는 내가 파일을 얻을 자사의 라인에이 파일을 분할 할 다음을 확인해야합니다 이런 식으로 :

this is a line 
and this is a line 

문제는, 심지어는 Windows 텍스트 편집기로 열어도 파일이 커지므로 문제가됩니다.

C#, Java 또는 Python으로 언급 한 것처럼이 파일을 분할 할 수 있습니까? 뭐죠 내 CPU를 과용하지 않는 최고의 soultion 것입니다.

+4

'sed' 또는 스크립팅 도구를 사용할 수 없습니까? – harsh

+0

ROW_DEL을 가상 결말이라고 부르는 이유는 무엇입니까? ROW_DEL은 파일에서 연속 된 문자입니까? 문제는 해결하기 쉽습니다.하지만이 점은 당혹 스럽습니다. – eyquem

+0

고정 크기 블록으로 파일을 읽으십시오. StreamReader 문서 (http://docs.python.org/release/2.4/lib/stream-reader-objects.html)에서'read' 문서를 확인하십시오. –

답변

1

실제로 텍스트의 500MB는 그리 크지 않습니다. 단지 메모장이 짜증납니다. 당신은 아마 당신이 창문에있어 이후로 사용할 수 나오지도 있지만, 적어도 파이썬에서 순진 솔루션을 시도하지 않는다, 나는 그것이 잘 작동합니다 생각 :

import os 
with open('infile.txt') as f_in, open('outfile.txt', 'w') as f_out: 
    f_out.write(f_in.read().replace('ROW_DEL ', os.linesep)) 
+1

+1 이것이 왜 실제로는 즉시 작동하고 질문에 답하는 이유는 확실하지 않습니다. 어쩌면''ROW_DEL ''은''ROW_DEL''이어야합니다. – jamylak

+1

<3sek에서 실행되며 모든 작업이 완료되었습니다 :) 감사합니다. – gurehbgui

+0

더 큰 파일을 읽을 때 당신의 답은 치명적일 수 있습니다. 검색된 하위 문자열, 팝 프론트의 길이와 동일한 길이의 벡터를 채우기 위해 char로 읽는다면 훨씬 시간이 많이 걸리지 만 더 안전한 방법으로 갈 수 있습니다. –

1

이 파일을 청크로 읽습니다. 예를 들어, C#에서 StreamReader.ReadBlock을 사용하십시오. 거기에 읽을 수있는 최대 문자 수를 설정할 수 있습니다.

읽은 각 청크에 대해 ROW_DEL\r\n으로 대체하고 새 파일에 추가 할 수 있습니다.

방금 ​​읽은 문자의 수만큼 현재 색인을 늘리는 것을 잊지 마십시오.

+5

ROW_DEL이 두 개의 청크로 분할되면 어떨까요? – I4V

+0

오른쪽 ..이 경우에는 청크의 마지막 글자가'ROW_DEL'의 일부인지 확인하고 필요한 경우 더 적은 문자를 읽으십시오. 읽고 싶은 양을 완전히 제어 할 수 있으므로 문제가되지 않아야합니다. –

1

것은 여기 내 솔루션입니다.
ŁukaszW.pl이 준 특이한 경우를 돌보고 싶다면 쉽게 작성할 수 있지만 코드 작성은 쉽지 않습니다.

특이한 경우는 구분 기호 ROW_DEL이 두 개의 읽기 청크 (I4V가 지적한 것처럼)로 분할되고, 두 개의 연속 청크가 두 개의 읽기 청크로 분할 된 연속 ROW_DEL 인 경우 더욱 현저합니다.

ROW_DEL이 가능한 줄 바꾸기 ('\r', '\n', '\r\n')보다 길기 때문에 파일에서 OS에서 사용하는 개행 문자로 대체 할 수 있습니다. 그래서 필자는 그 자체로 파일을 재 작성하려고했다.
모드 'r+'을 사용하기 때문에 새 파일을 만들지 않습니다.
바이너리 모드 'b'을 반드시 사용해야합니다.

원리 X 세퍼레이터의 길이와 wher X 추가 캐릭터 (현실의 크기는 예를 들어 262144 일 것이다) 덩어리를 읽어 -1.
그런 다음 구분 기호가 청크의 끝에 + x 문자가 있는지 검사합니다.
ROW_DEL의 변환이 수행되기 전에 청크가 짧아 지거나없는 경우 해당 위치에 다시 씁니다.

누드 코드는 다음과 같습니다

text = ('The hospital roommate of a man infected ROW_DEL' 
     'with novel coronavirus (NCoV)ROW_DEL' 
     '—a SARS-related virus first identified ROW_DELROW_DEL' 
     'last year and already linked to 18 deaths—ROW_DEL' 
     'has contracted the illness himself, ROW_DEL' 
     'intensifying concerns about the ROW_DEL' 
     "virus's ability to spread ROW_DEL" 
     'from person to person.') 

with open('eessaa.txt','w') as f: 
    f.write(text) 

with open('eessaa.txt','rb') as f: 
    ch = f.read() 
    print ch.replace('ROW_DEL','ROW_DEL\n') 
    print '\nlength of the text : %d chars\n' % len(text) 

#========================================== 

from os.path import getsize 
from os import fsync,linesep 

def rewrite(whichfile,sep,chunk_length,OSeol=linesep): 
    if chunk_length<len(sep): 
     print 'Length of second argument, %d , is '\ 
       'the minimum value for the third argument'\ 
       % len(sep) 
     return 

    x = len(sep)-1 
    x2 = 2*x 
    file_length = getsize(whichfile) 
    with open(whichfile,'rb+') as fR,\ 
     open(whichfile,'rb+') as fW: 
     while True: 
      chunk = fR.read(chunk_length) 
      pch = fR.tell() 
      twelve = chunk[-x:] + fR.read(x) 
      ptw = fR.tell() 

      if sep in twelve: 
       pt = twelve.find(sep) 
       m = ("\n !! %r is " 
        "at position %d in twelve !!" % (sep,pt)) 
       y = chunk[0:-x+pt].replace(sep,OSeol) 
      else: 
       pt = x 
       m = '' 
       y = chunk.replace(sep,OSeol) 

      pos = fW.tell() 
      fW.write(y) 
      fW.flush() 
      fsync(fW.fileno()) 

      if fR.tell()<file_length: 
       fR.seek(-x2+pt,1) 
      else: 
       fW.truncate() 
       break 

rewrite('eessaa.txt','ROW_DEL',14) 

with open('eessaa.txt','rb') as f: 
    ch = f.read() 
    print '\n'.join(repr(line)[1:-1] for line in ch.splitlines(1)) 
    print '\nlength of the text : %d chars\n' % len(ch) 

가 실행을 수행하려면 여기 모두 함께 메시지를 출력 다른 코드입니다 :

text = ('The hospital roommate of a man infected ROW_DEL' 
     'with novel coronavirus (NCoV)ROW_DEL' 
     '—a SARS-related virus first identified ROW_DELROW_DEL' 
     'last year and already linked to 18 deaths—ROW_DEL' 
     'has contracted the illness himself, ROW_DEL' 
     'intensifying concerns about the ROW_DEL' 
     "virus's ability to spread ROW_DEL" 
     'from person to person.') 

with open('eessaa.txt','w') as f: 
    f.write(text) 

with open('eessaa.txt','rb') as f: 
    ch = f.read() 
    print ch.replace('ROW_DEL','ROW_DEL\n') 
    print '\nlength of the text : %d chars\n' % len(text) 

#========================================== 

from os.path import getsize 
from os import fsync,linesep 

def rewrite(whichfile,sep,chunk_length,OSeol=linesep): 
    if chunk_length<len(sep): 
     print 'Length of second argument, %d , is '\ 
       'the minimum value for the third argument'\ 
       % len(sep) 
     return 

    x = len(sep)-1 
    x2 = 2*x 
    file_length = getsize(whichfile) 
    with open(whichfile,'rb+') as fR,\ 
     open(whichfile,'rb+') as fW: 
     while True: 
      chunk = fR.read(chunk_length) 
      pch = fR.tell() 
      twelve = chunk[-x:] + fR.read(x) 
      ptw = fR.tell() 

      if sep in twelve: 
       pt = twelve.find(sep) 
       m = ("\n !! %r is " 
        "at position %d in twelve !!" % (sep,pt)) 
       y = chunk[0:-x+pt].replace(sep,OSeol) 
      else: 
       pt = x 
       m = '' 
       y = chunk.replace(sep,OSeol) 
      print ('chunk == %r %d chars\n' 
        ' -> fR now at position %d\n' 
        'twelve == %r %d chars %s\n' 
        ' -> fR now at position %d' 
        % (chunk ,len(chunk),  pch, 
         twelve,len(twelve),m, ptw)) 

      pos = fW.tell() 
      fW.write(y) 
      fW.flush() 
      fsync(fW.fileno()) 
      print ('   %r %d long\n' 
        ' has been written from position %d\n' 
        ' => fW now at position %d' 
        % (y,len(y),pos,fW.tell())) 

      if fR.tell()<file_length: 
       fR.seek(-x2+pt,1) 
       print ' -> fR moved %d characters back to position %d'\ 
         % (x2-pt,fR.tell()) 
      else: 
       print (" => fR is at position %d == file's size\n" 
         ' File has thoroughly been read' 
         % fR.tell()) 
       fW.truncate() 
       break 

      raw_input('\npress any key to continue') 


rewrite('eessaa.txt','ROW_DEL',14) 

with open('eessaa.txt','rb') as f: 
    ch = f.read() 
    print '\n'.join(repr(line)[1:-1] for line in ch.splitlines(1)) 
    print '\nlength of the text : %d chars\n' % len(ch) 

청크의 끝의 치료에 약간 미묘있다가 ROW_DEL이 두 개의 청크에 걸쳐 있고 두 개의 ROW_DEL이 연속적인지 여부를 감지합니다. 그렇기 때문에 나는 내 솔루션을 게시하는 데 오랜 시간이 걸렸습니다. sep이 걸려 있는지 여부에 따라 또는 fR.seek(-x,1)뿐 아니라 마침내 fR.seek(-x2+pt,1)을 작성해야했습니다 (2 * x는 코드에서 x2이며 ROW_DEL x와 x2는 6 및 12). 이 점에 관심이있는 사람은 if 'ROW_DEL' is in twelve 섹션에있는 코드를 변경하여 검토 할 것입니다.

관련 문제