문제

파일과 같은 객체의 끝을 누르기 전까지는 반복해야하지만 "명백한 방법"을 찾지 못해서 무언가를 간과하고있는 것으로 의심됩니다. :-)

스트림이 있습니다 (이 경우 Stringio 객체이지만 일반적인 경우에도 궁금합니다).u003Clength>u003Cdata> "형식, 예를 들어 :

data = StringIO("\x07\x00\x00\x00foobar\x00\x04\x00\x00\x00baz\x00")

이제 이것을 읽을 수있는 유일한 명확한 방법은 초기화 된 루프를 사용하는 것입니다.

len_name = data.read(4)

while len_name != "":
    len_name = struct.unpack("<I", len_name)[0]
    names.append(data.read(len_name))

    len_name = data.read(4)

C와 같은 언어로, 나는 단지 read(4) 에서 while테스트 조항이지만 물론 파이썬에는 효과가 없습니다. 이것을 달성하는 더 좋은 방법에 대한 생각이 있습니까?

도움이 되었습니까?

해결책

반복을 결합 할 수 있습니다 iter () 센티넬과 함께 :

for block in iter(lambda: file_obj.read(4), ""):
  use(block)

다른 팁

텍스트 파일에서 줄을 반복하는 방법을 보셨습니까?

for line in file_obj:
  use(line)

자신의 발전기로 똑같은 일을 할 수 있습니다.

def read_blocks(file_obj, size):
  while True:
    data = file_obj.read(size)
    if not data:
      break
    yield data

for block in read_blocks(file_obj, 4):
  use(block)

또한보십시오:

나는 이미 언급 된 반복 기반 솔루션을 선호하여 이것을 For-loop로 바꾸는 것을 선호합니다. 직접 작성된 또 다른 솔루션은 Knuth의 "루프 앤 반"입니다.

while 1:
    len_name = data.read(4)
    if not len_name:
        break
    names.append(data.read(len_name))

당신은 그것이 자체 발전기에 쉽게 들어오는 방법을 비교하여 for-loop로 사용하는 방법을 볼 수 있습니다.

예측 한 바와 같이, 일반적이고 가장 인기있는 답변은 매우 전문화 된 발전기를 사용하여 "한 번에 4 바이트를 읽습니다". 때때로 일반성은 어렵지 않습니다 (그리고 훨씬 더 보람있는 ;-), 그래서, 나는 대신 다음과 같은 일반적인 해결책을 제안했습니다.

import operator
def funlooper(afun, *a, **k):
  wearedone = k.pop('wearedone', operator.not_)
  while True:
    data = afun(*a, **k)
    if wearedone(data): break
    yield data

이제 원하는 루프 헤더는 다음과 같습니다. for len_name in funlooper(data.read, 4):.

편집하다: wearedone 의견이 저의 약간 덜 일반적인 이전 버전을 고발 한 이후 관용 if not data:) 모든 것의 "숨겨진 의존성"의 경우!-)

평소 스위스 군대의 루핑 나이프, itertools, 물론 평소와 같이 괜찮습니다.

import itertools as it

for len_name in it.takewhile(bool, it.imap(data.read, it.repeat(4))): ...

또는 상당히 동등하게 :

import itertools as it

def loop(pred, fun, *args):
  return it.takewhile(pred, it.starmap(fun, it.repeat(args)))

for len_name in loop(bool, data.read, 4): ...

Python의 EOF 마커는 빈 문자열이므로 반복자에 이것을 마무리하는 기능을 작성하지 않고 얻을 수있는 최선에 가깝습니다. 나는 조금 더 피스닉 방식으로 글을 쓸 수 있습니다. while 처럼:

while len_name:
    len_name = struct.unpack("<I", len_name)[0]
    names.append(data.read(len_name))
    len_name = data.read(4)

가독성에 대한 Tendayi의 제안 RE 기능 및 반복자와 함께 갈 것입니다.

def read4():
    len_name = data.read(4)
    if len_name:
        len_name = struct.unpack("<I", len_name)[0]
        return data.read(len_name)
    else:
        raise StopIteration

for d in iter(read4, ''):
    names.append(d)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top