본문 바로가기

언어/Python

[ Python ] struct를 사용해서 little/big endian으로 파일 읽고 쓰기

반응형

struct 패키지는 Python에서 바이너리 데이터를 다룰 때 매우 유용한 도구입니다. 이 패키지를 사용하면 데이터를 특정한 바이트 순서(endianness)로 직렬화하거나 직렬화된 데이터를 파싱할 수 있습니다. 이 패키지의 핵심 기능 중 하나는 데이터의 바이트 순서를 지정할 수 있다는 것입니다.

엔디언(Endianness) 개념

엔디언은 멀티바이트 데이터를 메모리에 저장할 때 바이트의 순서를 정의하는 방식입니다.

  • 빅 엔디언 (Big Endian): 가장 중요한 바이트(Most Significant Byte, MSB)가 가장 앞에 오며, 가장 덜 중요한 바이트(Least Significant Byte, LSB)는 가장 뒤에 위치합니다. 인간이 숫자를 읽는 방식과 비슷합니다.
  • 리틀 엔디언 (Little Endian): 가장 덜 중요한 바이트(LSB)가 가장 앞에 오고, 가장 중요한 바이트(MSB)는 가장 뒤에 위치합니다. 이것은 Intel 아키텍처의 기본 방식입니다.

struct 모듈에서의 사용

struct 모듈은 데이터의 패킹(packing) 및 언패킹(unpacking)을 위한 기능을 제공합니다. 엔디언을 지정하기 위해 포맷 문자열의 첫 글자로 엔디언 타입을 명시할 수 있습니다:

  • <: 리틀 엔디언 (Little Endian)
  • >: 빅 엔디언 (Big Endian)
  • !: 네트워크 바이트 순서 (Network order, Big Endian과 동일)

이러한 포맷 문자는 데이터가 패킹되거나 언패킹될 때 어떤 순서로 바이트를 처리할지 지정해줍니다.

예제

아래 예제에서는 struct 모듈을 사용하여 숫자 1024를 리틀 엔디언과 빅 엔디언 형식으로 패킹하고 다시 언패킹하는 방법을 보여줍니다.

import struct

# 숫자 1024를 리틀 엔디언과 빅 엔디언 형식으로 패킹
number = 1024

# 리틀 엔디언으로 패킹 ('<H'는 리틀 엔디언, 2바이트 부호 없는 정수)
little_endian_packed = struct.pack('<H', number)
print(f"리틀 엔디언으로 패킹된 데이터: {little_endian_packed}")

# 빅 엔디언으로 패킹 ('>H'는 빅 엔디언, 2바이트 부호 없는 정수)
big_endian_packed = struct.pack('>H', number)
print(f"빅 엔디언으로 패킹된 데이터: {big_endian_packed}")

# 리틀 엔디언으로 패킹된 데이터 언패킹
unpacked_little_endian = struct.unpack('<H', little_endian_packed)[0]
print(f"리틀 엔디언으로 언패킹된 숫자: {unpacked_little_endian}")

# 빅 엔디언으로 패킹된 데이터 언패킹
unpacked_big_endian = struct.unpack('>H', big_endian_packed)[0]
print(f"빅 엔디언으로 언패킹된 숫자: {unpacked_big_endian}")

실행 결과

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.

리틀 엔디언으로 패킹된 데이터: b'\x00\x04'
빅 엔디언으로 패킹된 데이터: b'\x04\x00'
리틀 엔디언으로 언패킹된 숫자: 1024
빅 엔디언으로 언패킹된 숫자: 1024

이 예제에서 볼 수 있듯이, 동일한 숫자 1024가 리틀 엔디언과 빅 엔디언으로 각각 다른 순서의 바이트로 패킹됩니다. 이 패킹된 데이터를 언패킹할 때는 올바른 엔디언 타입을 사용해야 올바른 값이 반환됩니다.

요약

  • struct 모듈을 사용하여 리틀 엔디언과 빅 엔디언 형식으로 데이터를 패킹하고 언패킹할 수 있습니다.
  • 포맷 문자열의 첫 글자로 엔디언을 지정할 수 있으며, <는 리틀 엔디언, >는 빅 엔디언을 나타냅니다.
  • 데이터가 패킹될 때 바이트 순서를 적절히 설정해야 하며, 언패킹 시에도 동일한 바이트 순서를 사용해야 합니다.
반응형