자바에서 double 형태의 데이터를 바이너리 파일로 저장한 후, 파이썬에서 이를 읽어들이는데 자꾸 다른 값을 읽는 문제가 있었다.
이는 자바와 파이썬이 서로 다른 순서로 바이트 정보를 저장하기 때문이다.
바이트 저장 순서로는 빅 엔디안, 리를 엔디안 두 가지가 있다.
- 자바: 빅 엔디안(big endian)을 따름.
- 파이썬: 리를 엔디안(little endian)을 따름.
빅 엔디안은 시작 주소에 상위 바이트(앞 부분)부터 기록 하고, 리를 엔디안은 시작 주소에 하위 바이트(뒷 부분)부터 기록한다.
예를 들어, 0x12345678의 바이너리 값을 저장한다면, 아래와 같이 다른 순서로 데이터를 저장한다.
- 빅 엔디안(자바): 0x12, 0x34, 0x56, 0x78
- 리를 엔디안(파이썬): 0x78, 0x56, 0x34, 0x12
따라서 자바에서 저장한 바이너리 파일을 파이썬에서 읽기 위해서는 엔디안 변환을 해주어야 한다.
아래는 위 문제를 해결한 실제 사용한 파이썬 코드이다.
import struct
with open('./dataset/' + f, 'rb') as r:
data = r.read()
b_list = [(data[x:x+8], data[x+8:x+16]) for x in range(0, len(data), 16)]
points = []
for bx, by in b_list:
x = struct.unpack('>d', bx)[0]
y = struct.unpack('>d', by)[0]
points.append((x, y))
읽어오는 데이터가 double 형태이기 때문에 8byte 단위로 데이터를 잘라 b_list를 만들었다.
파이썬에서는 struct.unpack을 통해 바이트 형태의 데이터를 사용하기 편한 데이터로 변경할 수 있다.
'>d'은 unpack의 변형 형태(format)이다.
>는 빅 에디안으로 읽겠다는 의미이고, d는 double 형태의 데이터로 변형하겠다는 소리다.
(파이썬은 double 타입이 없기에 8byte float으로 변형한다.)
struct의 변형 형태에 대해 더 많은 정보를 얻고싶으면, 아래 링크에 가면 볼 수 있다.
영문 페이지지만, 테이블로 정리되어 있기 때문에 쉽게 알 수 있다.
https://docs.python.org/2/library/struct.html#struct.unpack_from
7.3. struct — Interpret strings as packed binary data — Python 2.7.17 documentation
7.3. struct — Interpret strings as packed binary data This module performs conversions between Python values and C structs represented as Python strings. This can be used in handling binary data stored in files or from network connections, among other sour
docs.python.org
이 글이 도움이 되었으면 좋겠다.