프로그래밍

자바(Java)와 파이썬(Python)의 바이너리(binary) 차이

자바에서 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

 

이 글이 도움이 되었으면 좋겠다.