2013-12-16 2 views
2

계산 한 crc를 기존 바이너리 파일에 추가하고 싶습니다.파이썬으로 바이너리 파일에 데이터 바이트 추가하기

예를 들어, crc는 0x55667788입니다.

파일의 끝에 0x55, 0x66, 0x77 및 0x88을 추가하고 싶습니다.

예를 들어 파일을 HexEdit에서 열면 파일의 마지막 4 바이트에 0x55667788이 표시됩니다. 여기

내 코드는 지금까지 있습니다 :

fileopen = askopenfilename() 
filename = open(fileopen, 'rb+') 
filedata = filename.read() 
filecrc32 = hex(binascii.crc32(filedata)) 
filename.seek(0,2) 
filename.write(filecrc32) 
filename.close() 

나는 다음과 같은 오류 얻을 :

File "C:\Users\cjackel\openfile.py", line 9, in <module> 
filename.write(filecrc32) 
TypeError: 'str' does not support the buffer interface 

어떤 제안?

+0

당신은에서 파일을 여는 것 * 바이너리 * 모드이지만 * 텍스트 * 문자열을 쓰려고합니다. 먼저 문자열에 대한 인코딩을 선택하거나 다른 이진 데이터를 작성해야합니다. – millimoose

답변

4

hex 함수는 문자열을 반환합니다. 이 경우에는 다음과 같이 귀하의 4 바이트 수를 나타내는 10 진수 문자열을 가지고 :

파이썬 2.X에서
'0x55667788' 

, 당신은 이진 파일이 잘못된 데이터를 쓸 수 것 (원하는 4 바이트가 아닌 30 78 35 35 36 36 37 37 38 38 인 10 바이트로 표시됩니다 (55 66 77 88). Python 3.x는 더 똑똑하고 이 아닌 bytes (또는 bytearray 또는 이와 비슷한) 만 이진 파일에 쓸 수 있습니다.


여기서 원하는 것은 16 진수 문자열이 아니라 실제 바이트입니다.

원하는 바이트를 설명하는 방법은 big-endian order입니다. 대부분의 컴퓨터에서 "네이티브"주문은 리틀 엔디안과 반대이며, 이는 대신 0x88776655이됩니다. 파이썬 3.2 이상에서

는 것을 얻을 수있는 가장 간단한 방법은 int.to_bytes 방법 :

filecrc = binascii.crc32(filedata).to_bytes(4, byteorder='big', signed=False) 

합니다 (signed=False이 정말 필요하지 않습니다이 기본이지만, 그것이 명시 적으로 만드는 좋은 방법이기 때문에

filecrc = struct.pack('>I', binascii.crc32(filedata)) 
: 당신은 이전 버전과 붙어 있다면, 당신은 struct 모듈을 사용할 수 있습니다 당신은 확실히 부호없는 32 비트 정수를 처리하고 있음)

.

>은 빅 엔디안을 의미하고 I은 부호없는 4 바이트 정수를 의미합니다. 그래서, 이것은 같은 것을 반환합니다. 어떤 경우이든 b'\x55\x66\x77\x88' (또는 파이썬은 repr입니다. b'\Ufw\x88')입니다. 어떤 초보자는 "버퍼 인터페이스"는 3.X 문서는 Buffer Protocol를 호출하고,이 단지의 일부로 문서화 특히 이후 (무엇인지 어떤 생각을해야 할 것하지 않기 때문에


오류는 약간 비밀이다 CPython의 C 확장 API ...). 그러나 실제로는 bytes-like object이 필요합니다. 일반적으로이 오류는 문자열을 UTF-8 또는 다른 인코딩으로 인코딩하는 것을 잊어 버린 것을 의미합니다.그러나 인코딩 된 텍스트가 아닌 실제 이진 데이터를 쓰려고 할 때도 마찬가지입니다.

+1

Python 3.2 이상에서'binascii.crc32 (filedata) .to_bytes (4, byteorder = 'big')'를 사용할 수 있습니다. – jfs

+0

@JFSebastian : 음, 분명히'signed = False'를 사용 하겠지만 그렇지 않으면, 네, 훨씬 더 간단합니다. 그리고 나는 3.2 이미 그것을 잊었다. 감사! – abarnert

+0

동의합니다. 부호없는 정수를 반환하도록 문서화 된'binascii.crc32()'와 디폴트 인'signed = False'에도 불구하고, 명시 적'signed = False'는 6 개월 만에 읽기가 쉬워졌고 모든 것을 잊었습니다. – jfs

0

데이터를 직렬화해야합니다. 직렬화는 전체 숫자에서 관련 바이트를 으로 가져 오는 프로세스입니다. 귀하의 CRC는 4 바이트 숫자입니다. 각각의 4 바이트는 다음과 같이 목록에 검색 할 수 있습니다 :

serialized_crc = [(filecrc32 >> 24) & 0xFF,(filecrc32 >> 16) & 0xFF, 
       (filecrc32 >> 8) & 0xFF,filecrc32 & 0xFF] 
CRC가 다음 아래와 같이 된 ByteArray로 변환하여 파일에 기록 할 수

:

filename.write(bytearray(serialized_crc)) 
관련 문제