Python 바 이 너 리 배열 데 이 터 를 읽 고 쓰 는 방법

문제.
파 이 썬 모듈 에 바 이 너 리 배열 의 구조 화 된 데 이 터 를 읽 고 싶 습 니 다.
해결 방안struct모듈 로 바 이 너 리 데 이 터 를 처리 할 수 있 습 니 다.다음은 예제 코드 입 니 다.Python 모듈 목록 을 바 이 너 리 파일 에 기록 하고struct각 모듈 을 하나의 구조 체 로 인 코딩 합 니 다.

from struct import Struct
def write_records(records, format, f):
  '''
  Write a sequence of tuples to a binary file of structures.
  '''
  record_struct = Struct(format)
  for r in records:
    f.write(record_struct.pack(*r))

# Example
if __name__ == '__main__':
  records = [ (1, 2.3, 4.5),
        (6, 7.8, 9.0),
        (12, 13.4, 56.7) ]
  with open('data.b', 'wb') as f:
    write_records(records, '<idd', f)
이 파일 을 읽 고 원 그룹 목록 으로 돌아 가 는 방법 은 여러 가지 가 있 습 니 다.우선,블록 형식 으로 파일 을 추가 로 읽 으 려 면 이렇게 할 수 있 습 니 다.

from struct import Struct

def read_records(format, f):
  record_struct = Struct(format)
  chunks = iter(lambda: f.read(record_struct.size), b'')
  return (record_struct.unpack(chunk) for chunk in chunks)

# Example
if __name__ == '__main__':
  with open('data.b','rb') as f:
    for rec in read_records('<idd', f):
      # Process rec
      ...
모든 파일 을 한 바이트 문자열 에 한꺼번에 읽 고 나 서 조각 을 나 누 어 분석 하고 싶다 면.그러면 너 는 이렇게 할 수 있다.

from struct import Struct

def unpack_records(format, data):
  record_struct = Struct(format)
  return (record_struct.unpack_from(data, offset)
      for offset in range(0, len(data), record_struct.size))

# Example
if __name__ == '__main__':
  with open('data.b', 'rb') as f:
    data = f.read()
  for rec in unpack_records('<idd', data):
    # Process rec
    ...
두 가지 상황 에서 결 과 는 이 파일 을 만 드 는 원본 그룹 으로 되 돌아 갈 수 있 는 교체 가능 한 대상 입 니 다.
토론 하 다.
바 이 너 리 데 이 터 를 인 코딩 하고 디 코딩 해 야 하 는 프로그램 에 서 는 보통struct모듈 을 사용 합 니 다.새로운 구조 체 를 설명 하기 위해 서 는 이렇게Struct인 스 턴 스 를 만 들 면 됩 니 다.

# Little endian 32-bit integer, two double precision floats
record_struct = Struct('<idd')
구조 체 는 보통 구조 코드 값 i,d,f 등[참고파 이 썬 문서]을 사용한다.이 코드 들 은 32 비트 정수,64 비트 부동 소수점,32 비트 부동 소수점 등 특정한 바 이 너 리 데이터 형식 을 대표 한다.첫 번 째 문자<바이트 순 서 를 지 정 했 습 니 다.이 예 에서 그것 은'낮은 위치 가 앞 에 있다'는 것 을 나타 낸다.이 문 자 를>로 변경 하면 상위 가 앞 에 있 거나!네트워크 바이트 순 서 를 나타 낸다.
발생 하 는Struct인 스 턴 스 는 해당 유형의 구 조 를 조작 하 는 속성 과 방법 이 많다.size속성 은 구조의 바이트 수 를 포함 하 는데 이것 은 I/O 작업 에 매우 유용 하 다.pack() unpack() 방법 은 데 이 터 를 포장 하고 해제 하 는 데 사용 된다.예 를 들 면:

>>> from struct import Struct
>>> record_struct = Struct('<idd')
>>> record_struct.size
20
>>> record_struct.pack(1, 2.0, 3.0)
b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x08@'
>>> record_struct.unpack(_)
(1, 2.0, 3.0)
>>>
가끔 은pack() unpack() 조작 이 모듈 급 함수 로 호출 되 는 것 을 볼 수 있 습 니 다.아래 와 같 습 니 다.

>>> import struct
>>> struct.pack('<idd', 1, 2.0, 3.0)
b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x08@'
>>> struct.unpack('<idd', _)
(1, 2.0, 3.0)
>>>
이렇게 하면 일 을 할 수 있 지만 인 스 턴 스 방법 만큼 우아 하지 않 은 것 같 습 니 다.특히 코드 에 같은 구조 가 여러 곳 에 나 타 났 을 때.하나의Struct 인 스 턴 스 를 만 들 면 형식 코드 는 한 번 만 지정 되 고 모든 작업 이 집중 적 으로 처 리 됩 니 다.이렇게 되면 코드 유지 보수 가 더욱 간단 해진 다.
바 이 너 리 구 조 를 읽 는 코드 는 매우 재 미 있 고 아름 다운 프로 그래 밍 기술 을 사용 해 야 한다.함수read_records 에서iter() 는 고정 크기 의 데이터 블록 을 되 돌려 주 는 교체 기 를 만 드 는 데 사 용 됩 니 다.이 교체 기 는 사용자 가 제공 하 는 호출 가능 한 대상(예 를 들 어lambda: f.read(record_struct.size) 을 계속 호출 하여 특수 한 값(예 를 들 어 b')을 되 돌려 줄 때 까지 교체 가 중단 된다.예 를 들 면:

>>> f = open('data.b', 'rb')
>>> chunks = iter(lambda: f.read(20), b'')
>>> chunks
<callable_iterator object at 0x10069e6d0>
>>> for chk in chunks:
... print(chk)
...
b'\x01\x00\x00\x00ffffff\x02@\x00\x00\x00\x00\x00\x00\x12@'
b'\x06\x00\x00\x00333333\x1f@\x00\x00\x00\x00\x00\x00"@'
b'\x0c\x00\x00\x00\xcd\xcc\xcc\xcc\xcc\xcc*@\x9a\x99\x99\x99\x99YL@'
>>>
보시 다시 피 교체 가능 한 대상 을 만 드 는 이 유 는 생 성기 유도 로 기록 을 만 들 수 있 기 때 문 입 니 다.만약 당신 이 이런 기술 을 사용 하지 않 는 다 면 코드 는 아래 와 같이 될 수 있 습 니 다.

def read_records(format, f):
  record_struct = Struct(format)
  while True:
    chk = f.read(record_struct.size)
    if chk == b'':
      break
    yield record_struct.unpack(chk)
함수 unpack_records() 에서 다른 방법unpack_from() 을 사용 했다.unpack_from()은 대형 바 이 너 리 배열 에서 바 이 너 리 데 이 터 를 추출 하 는 데 매우 유용 합 니 다.임시 대상 이 생기 거나 메모리 복사 작업 을 하지 않 기 때 문 입 니 다.바이트 문자열(또는 배열)과 바이트 오프셋 만 주면 그 위치 에서 데 이 터 를 직접 풀 수 있 습 니 다.
만약 당신 이unpack() 을 사용 하여 대체unpack_from() 한다 면,당신 은 코드 를 수정 하여 대량의 작은 절편 을 구성 하고 오프셋 을 계산 해 야 합 니 다.예 를 들 면:

def unpack_records(format, data):
  record_struct = Struct(format)
  return (record_struct.unpack(data[offset:offset + record_struct.size])
      for offset in range(0, len(data), record_struct.size))
이 방안 은 코드 가 복잡 해 보 이 는 것 외 에 도 많은 추가 작업 을 해 야 한다.왜냐하면 그것 은 대량의 오프셋 계산,데이터 복제 와 구조 가 작은 절편 대상 을 실 행 했 기 때문이다.읽 은 대형 바이트 문자열 에서 대량의 구조 체 를 풀 려 고 한다 면unpack_from() 더 잘 할 것 입 니 다.
패 키 지 를 풀 때collections 모듈 의 이름 을 가 진 메타 그룹 대상 은 사용 하고 싶 은 것 일 수도 있 습 니 다.원 그룹 으로 돌아 가 속성 이름 을 설정 할 수 있 습 니 다.예 를 들 면:

from collections import namedtuple

Record = namedtuple('Record', ['kind','x','y'])

with open('data.p', 'rb') as f:
  records = (Record(*r) for r in read_records('<idd', f))

for r in records:
  print(r.kind, r.x, r.y)
프로그램 이 바 이 너 리 데 이 터 를 많이 처리 해 야 한다 면numpy모듈 을 사용 하 는 것 이 좋 습 니 다.예 를 들 어 원 그룹 목록 이 아 닌 구조 화 된 배열 로 바 이 너 리 데 이 터 를 읽 을 수 있 습 니 다.아래 처럼:

>>> import numpy as np
>>> f = open('data.b', 'rb')
>>> records = np.fromfile(f, dtype='<i,<d,<d')
>>> records
array([(1, 2.3, 4.5), (6, 7.8, 9.0), (12, 13.4, 56.7)],
dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', '<f8')])
>>> records[0]
(1, 2.3, 4.5)
>>> records[1]
(6, 7.8, 9.0)
>>>
마지막 으로 알려 진 파일 형식(예 를 들 어 그림 형식,그래 픽 파일,HDF 5 등)에서 바 이 너 리 데 이 터 를 읽 을 필요 가 있 을 때 Python 이 기 존 모듈 을 제 공 했 는 지 확인 하 십시오.어 쩔 수 없 이 바퀴 를 다시 만 들 필요 가 없 기 때문이다.
이상 은 파 이 썬 이 바 이 너 리 배열 데 이 터 를 어떻게 읽 고 쓰 는 지 에 대한 상세 한 내용 입 니 다.파 이 썬 이 바 이 너 리 배열 데 이 터 를 읽 고 쓰 는 데 관 한 자 료 는 다른 관련 글 에 주목 하 십시오!

좋은 웹페이지 즐겨찾기