2009-12-17 6 views
0

파일의 모든 행을 반복하는 함수가 필요합니다.
가 여기에 지금까지 가지고 무엇을 : 파일의파이썬에서 문자 지정

def LineFeed(file): 
    ret = "" 
    for byte in file: 
     ret = ret + str(byte) 
     if str(byte) == '\r': 
      yield ret 
      ret = "" 

모든 라인 \ r을 (\하지 N)로 끝나는, 나는 "rb "모드에서 읽고 있어요, (I이 파일을 읽을 필요) 진. yield이 작동하고 아무 것도 반환하지 않습니다. 아마 비교에 문제가? 난 당신이 파이썬에서 바이트/문자를 표현하는 방법 단지 모르겠어요.

을 나는 아이디어를 얻고 만약 당신이 "rb"파일에 대해 루프를 반복한다면 바이트가 아닌 라인을 반복하려고 시도합니다 ... 어떻게 바이트를 반복 할 수 있습니까? 제 문제는 제가 h 표준 라인 결말. 또한 내 파일은 0x00 바이트로 채워져 있고 나는 그들을 모두 없애고 싶습니다. 그래서 두 번째 yield 함수가 필요하다고 생각합니다. 어떻게 구현할 수 있습니까? 파이썬에서 0x00 바이트를 나타내는 방법을 모르겠습니다. 또는 NULL char.

+1

는 NUL의 문자를 제거에 대한 또 다른 질문을하시기 바랍니다 :

당신이 당신의 굴복 라인이 아직 종료 R을 \ 싶은 가정. 한 게시물에 여러 질문이 작동하지 않습니다. – ddaa

답변

1

파일을 여는 방법을 제어하는 ​​경우 'rb'모드를 사용하는 경우 \ r은 줄 바꿈 문자로 인식되지 않으므로 유니버설 개행으로 파일을 여는 것이 좋습니다. 'Urb'를 사용하는 경우

유니버설 줄 바꿈을 사용할 때 \ r과 \ n의 구분이 손실되므로이 옵션은 \ r과 \ r을 이진 파일에 포함하지 않는 경우에만 작동합니다.

NUL = '\x00' 
def lines_without_nulls(path): 
    with open(path, 'Urb') as f: 
     for line in f: 
      yield line.replace(NUL, '').replace('\n', '\r') 
+0

윈도우에서 파이썬을 사용했기 때문에 오랫동안 그 이진 의미를 잊어 버렸습니다. 일반적으로 그것은 \ r과 \ n을 보존하는 것을 의미하며 이는 Windows에서만 필요합니다. 그래서 유니버설 + 바이너리는 일종의 모순입니다 (일단 바이너리를 사용하지 않는 유니버설을 사용하면 개조가 끝납니다). 나는 왜 누군가가 바이너리를 사용하는지 전혀 모르지만, 만약 당신이 정말로한다면, 나의 해결책은 'Urb'모드가 'Ub'모드와 같다고 생각하기 때문에 이해가되지 않는다. –

2

나는 "파일에서 x"가하는 것과 혼동한다고 생각한다. "file = open (file_name)"과 같은 핸들이 있다고 가정하면이 경우 바이트는 단일 문자가 아닌 전체 라인이됩니다. 따라서 전체 행이 단일 캐리지 리턴으로 구성된 경우에만 수익을 호출합니다. "바이트"를 "라인"으로 변경하고 두 번째 루프로 반복 해보십시오.

0

편집 :

  • string1 += string2 문자열 연결 속도가 느립니다. 문자열 목록에 합류 해보십시오.

  • ddaa가 맞습니다. - 이진 파일에 ASCII 만 포함되어있는 경우 struct 패키지가 필요하지 않습니다. 또한, 내 생성기는 EOF 전에 최종 '\ r'다음에 문자열을 반환합니다. 이 두 가지 사소한 수정을 통해 내 코드는 this more recent answer과 의심스러운 (사실상 동일한) 것입니다.

코드 싹둑 :

def LineFeed(f): 
    ret = [] 
    while True: 
     oneByte = f.read(1) 
     if not oneByte: break 
     # Return everything up to, but not including the carriage return 
     if oneByte == '\r': 
      yield ''.join(ret) 
      ret = [] 
     else: 
      ret.append(oneByte) 
    if oneByte: 
     yield ''.join(ret) 
if __name__ == '__main__': 
    lf = LineFeed(open('filename','rb')) 

    for something in lf: 
     doSomething(something) 
+0

여기서 struct를 사용하는 것이 중요하지 않습니다. 또한이 함수에는 버그가 있습니다. 마지막 \ r 뒤에는 텍스트가 삭제됩니다. – ddaa

+0

@ddaa : 좋은 지적; 결정된! – Pete

0

그래서, 문제는 행 분리로 '\r'를 사용하는 바이너리 모드에서 열려있는 파일의 라인을 반복한다. 파일이 바이너리 모드이므로 유니버설 뉴 라인 기능을 사용할 수 없으며 '\r'은 바이너리 모드에서 라인 구분자로 해석되지 않습니다. 문자로 파일 문자 읽기

파이썬에서 할 수있는 대단히 비효율적 인 일이지만 여기에 당신이 당신의 라인을 반복 수있는 방법은 다음과 같습니다

def cr_lines(the_file): 
    line = [] 
    while True: 
     byte = the_file.read(1) 
     if not byte: 
      break 
     line.append(byte) 
     if byte == '\r': 
      yield ''.join(line) 
      line = [] 
    if line: 
     yield ''.join(line) 

는 당신의 더 큰 덩어리를 읽을 필요가 더 효율적를 텍스트를 처리하고 반복자에서 버퍼링을 처리합니다. iterating하는 동안 당신이 이상한 버그를 얻을 수 있다는 것을 명심하십시오. 이러한 버그를 방지하려면 파일의 하위 클래스가 필요하므로 검색 할 때 버퍼를 제거 할 수 있습니다.

이디엄의 사용에 유의하십시오. +=으로 문자열을 누적하는 것은 성능이 좋지 않으며 시작 프로그래머가 자주 범하는 실수입니다.

+0

유니버설 뉴 라인을 사용할 수없는 이유는 무엇입니까? 유니버설 뉴 라인은 글쓰기와 호환되지 않지만 open ('cr_terminated.bin', 'Urb')은 잘 동작합니다. –

+0

OP는 그가 바이너리 모드로 파일을 열어야한다는 것을 나타내며 문서에는 " 'U'를 제공하면 파일을 텍스트 파일로 엽니 다"라고되어 있습니다. http://docs.python.org/library/functions.html#open – ddaa

2

왜이 파일이 무엇을 나타내는 지, 왜 '\ x00'이 많은지, 왜 바이너리 모드로 읽어야하는지 생각하면 근본적인 문제를 해결할 수 있습니다.

그렇지 않으면 다음 코드를 시도하십시오. 운영 체제의 라인 종료 규칙에 대한 의존성을 피할 수 있습니다.

lines = open("the_file", "rb").read().split("\r") 
for line in lines: 
    process(line) 

편집 : ASCII NUL ("NULL"이 아닌) 바이트는 "\ x00"입니다.

+0

+1 부조리 한 질문에 대한 제 솔직한 답변입니다. – hughdbrown

관련 문제