2014-02-28 4 views
2

.lrf 파일에서 일부 메타 데이터의 길이를 읽으려고합니다. (LoLReplay 프로그램과 함께 사용)파일에서 바이트를 읽는 방법

이 파일에는 실제로 설명서가 없지만 이미 C++에서이를 수행하는 방법을 알아 냈습니다. 여러 이유로 파이썬에서 프로젝트를 다시 작성하려고하지만 오류가 발생했습니다.

먼저 설명하기 위해, .lrf 파일은 다음 형식으로 파일의 시작 부분에 즉시 메타 데이터가 :

  • 처음 4 바이트 나에 대한 단서가 없다 무엇인가에 대한 것입니다.

  • 다음 4 바이트는 메타 데이터의 끝까지 16 진수로 메타 데이터의 길이를 저장합니다. 메타 데이터의 끝 부분은 재생 후 실제 내용입니다. 최초의 8 바이트 후

  • 바이트 JSON 형식

실제로 메타 데이터 길이를 읽는 데 문제의 메타 데이터입니다. 문자를 읽기 위해 노력하고있다

Traceback (most recent call last): 
    File "C:\Users\Donald\python\lolcogs\lolcogs_main.py", line 6, in <module> 
    lolcogs.getMetaLength() 
    File "C:\Users\Donald\python\lolcogs\LoLCogs.py", line 20, in getMetaLength 
    file.read(4) 
    File "C:\Python32\lib\encodings\cp1252.py", line 23, in decode 
    return codecs.charmap_decode(input,self.errors,decoding_table)[0] 
    UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 3648:  character maps to <undefined> 

내 추측은 그 읽기 (입니다) :이 함수를 호출 할 때

def getMetaLength(self): 
    try: 
     file = open(self.file,"r") 
    except IOError: 
     print ("Failed to open file.") 
     file.close() 
    #We need to skip the first 4 bytes. 
    file.read(4) 
    mdlength = file.read(4) 
    print(hex(mdlength)) 
    file.close() 

는, 쉘이 내용의 역 추적을 반환 : 이것은 내가 가지고있는 현재의 기능입니다 어떤 유니 코드 형식으로 인코딩되었지만, 이것들은 확실히 내가 읽으려고하는 바이트들입니다. 바이트로 읽는 방법이 있습니까? 또한 파일을 읽으려고 할 때 바이트를 건너 뛰는 더 좋은 방법이 있습니까?

+0

파일을 _binary mode_ :'f = open (self.file, "rb")'에서 열어보십시오. 또한'file' 형식의 이름과 충돌하기 때문에 이름을'file'로 지정하지 마십시오. –

+0

@PauloBu 더 이상 그런 유형이없는 것처럼 보이지만 ... –

+0

Python2.7에서 정의됩니다. 파이썬 3에서는. 하지만 OP의 코드를 읽고 그는 아마도 Python 3을 사용하므로 내 코멘트를 무시합니다. –

답변

1

파일을 이진 모드 (open(filename, 'rb'))로 열어야합니다.

1

파이썬 3에서는 파일이 기본적으로 시스템의 인코딩으로 텍스트 모드로 열립니다. 당신이로 실행됩니다

file = open(self.file, 'rb') 

또 다른 문제가 file.read(4) 당신에게합니다 (hex 기능을 이해하지 못하는) 4 바이트의 문자열을 줄 것입니다 : 당신은 바이너리 모드로 파일을 열어야합니다. 그리고 정수를 원할 수도 있습니다. 이를 위해서는 int.from_bytes을 참조하십시오.보다 일반적으로는 struct module을 참조하십시오. 그럼 당신은 너무로 16 진수 형식으로 해당 번호를 인쇄 할 수 있습니다

mdlength = int.from_bytes(file.read(4), byteorder='big') 
print(hex(mdlength)) 
+0

놀라운! int.from_bytes() 함수는 필자가 필요로하는 것입니다. C++에서는 동등한 함수가 있는지 모르지만 C++에서 수동으로이 작업을 수행해야하며 사용자의 주석을 읽을 때까지 수동으로 Python으로 처리하려고했습니다. 감사! – shadefinale

0

바이너리 파일은 바이너리 모드로 처리해야합니다 바이트를 건너 뛰는 경우

f = open(filename, 'rb') 

, 나는 일반적으로 파일 seek (SEEK_CUR 또는 SEEK_SET)를 사용하거나 내가 공식적으로 고민하고 싶지 않다면 나는 단지 file.read(n)을한다. 내가 진정으로 추구하는 시간은 내가 특정 위치로 뛰어 가고 싶을 때 뿐이다.

이진 데이터 해석하기 나는 단지 struct 모듈에 의해 제공되는 언팩 방법을 고수하고 있으며, 바이트 시퀀스를 int, float, char 등으로 해석할지 여부를 쉽게 정의 할 수 있습니다. 수년 동안 해왔으니 어쩌면 다른 대답에 설명 된 from_bytes 메서드와 같은 더 효율적인 접근법이있을 수 있습니다.한 번에 3 (부호) 정수에서 읽을 수있는

struct.unpack("3I", f.read(12)) 

등의 작업을 수행 할 수있는 구조체 모듈

. 그래서 예를 들어 당신이 역 설계 한 형식이 주어진다면 아마 말할 것입니다.

unk, size = struct.unpack("2I", f.read(8)) 
data = f.read(size) 
관련 문제