2012-05-23 5 views
3

저는 파이썬에 익숙한 초보자입니다. 나는 오히려 깊은 끝에 던져 버렸습니다. 약간의 배경 : 우리가 읽고있는 파일은 수중 음파 탐지기 카메라에서 가져온 것입니다. 지금은 날짜, 파일 이름, 프레임 수, 광선 수 등과 같은 파일에 기록 된 속성을 읽으려고합니다. 먼저 FILE 헤더를 읽으 려합니다. 그런 다음 각 프레임에 대해 FRAME 헤더를 읽고 싶습니다. 파일 헤더가 중단 된 프레임 헤더를 읽어야합니다 ...이 작업을 수행하려면 seek()이 필요하다고 생각합니다. 여기에 내가 그 정보는 프레임 헤더에 대한 끝나는 파일 헤더를 (성공적으로 완료) 읽고 시작, 현재 가지고있는 코드는 다음과 같습니다바이너리 파일을 읽는 동안 seek()

편집을 할 CODE : 이제

import math, struct 
def __init__(didson): 
    print "this better work" 

def get_file_header(data,offset=0): 
    fileheader={} 
    winlengths=[1.125,2.25,4.5,9,18,36] 
    fileheader['filetype']=struct.unpack("3s",didson_data[0:3]) 
    fileheader['fileversion']=struct.unpack('B',didson_data[3:4])[0] 
    fileheader['numframes']=struct.unpack('l',didson_data[4:8]) 
    fileheader['framerate']=struct.unpack('l',didson_data[8:12]) 
    fileheader['resolution']=struct.unpack('i',didson_data[12:16]) 
    fileheader['numbeams']=struct.unpack('i',didson_data[16:20]) 
    fileheader['samplerate']=struct.unpack('f',didson_data[20:24]) 
    fileheader['samplesperchannel']=struct.unpack('l',didson_data[24:28]) 
    fileheader['receivergain']=struct.unpack('l',didson_data[28:32]) 
    fileheader['windowstart']=struct.unpack('i',didson_data[32:36]) 
    fileheader['winlengthsindex']=struct.unpack('i',didson_data[36:40]) 
    fileheader['reverse']=struct.unpack('l',didson_data[40:44]) 
    fileheader['serialnumber']=struct.unpack('l',didson_data[44:48]) 
    fileheader['date']=struct.unpack("10s",didson_data[48:58]) 
    #fileheader['???']=struct.unpack('26s',didson_data[58:84]) 
    fileheader['idstring']=struct.unpack("33s",didson_data[84:117]) 
    #fileheader['????2']=struct.unpack('235s',didson_data[117:352]) 
    fileheader['framestart']=struct.unpack('i',didson_data[352:356]) 
    fileheader['frameend']=struct.unpack('i',didson_data[356:360]) 
    fileheader['timelapse']=struct.unpack('i',didson_data[360:364]) 
    fileheader['recordInterval']=struct.unpack('i',didson_data[364:368]) 
    fileheader['radioseconds']=struct.unpack('i',didson_data[368:372]) 
    fileheader['frameinterval']=struct.unpack('i',didson_data[372:376]) 

    return fileheader 




def num_datagrams(didson_data): 
    assert(len(didson_data) % datagram_size==0) 
    return len(didson_data)/datagram_size 

def get_offset(datagram_number): 
    return datagram_number * datagram_size 

def didson_print(fileheader): 
    print fileheader 
    for key in fileheader: 
     print ' ',key, fileheader[key] 


def main(): 
    didson_file=open('C:/vprice/DIDSON/DIDSON Data/test.ddf', 'rb') 
    didson_data=didson_file.read() 
    print 'Number of datagrams:', num_datagrams(didson_data) 
    didson_print(datagram) 


if __name__=='main': 
    main() 

내가 "주"를 실행하면, 윌 한 줄씩 읽을 수 있습니까? 라인 당 하나의 값인지 확실하지 않습니다 ... 기본적으로 살펴보고 바이트 값을 계산하여 어떤 헤더 값이 어디에 있는지 파악했습니다.

도움이 될 것입니다!

+1

'struct'는 문자열에서 데이터의 압축을 풉니 다. 그래서,'didson_data'는 문자열이어야합니다, 그러나 당신은 우리에게 파일로부터 그것을 읽는 코드를 보여주지 않았습니다. 파일에서 읽은 내용을 표시하지 않았으므로 표시 한 내용이 파일 위치를 변경해서는 안됩니다. 실제로 열린 파일에서 데이터를 읽으십니까? – steveha

+1

내가 가진 건 didson_data = didson_file.read() ...이 일을하는 가장 좋은 방법은 무엇입니까 (나는 내가 초급자라고 말할 때 농담하지 않는다 ... 나는 약간의 MATLAB 경험을 가지고 있지만, 그게 전부이다.)? 내가 fileheader를 인쇄 할 때, 그것이 의미하는 바라면 모든 올바른 매개 변수를 얻습니다. –

+0

'didson_file.read()'는 파일의 전체 내용을 메모리의 단일 문자열 변수로 슬쩍 할 것입니다. 그렇게하면 더 이상 찾을 필요가 없습니다. 당신은 그 문자열에 색인을하여 데이터를 가져올 수 있습니다. 또는 파일 데이터가 2 진수가 아니고 합리적인 선을 사용하는 경우 표준 Python 관용어를 사용할 수 있습니다 ... erm, 코드는 이러한 주석에 좋지 않습니다. 답변을 게시해야합니다. 제 대답을보세요. – steveha

답변

2

당신은 didson_data로 파일의 전체 내용을 읽고, 다시 제로로 파일 처리기 didson_file을 추구하고 didson_data에서 모든 필드를 분할과의 행/덩어리를 단계별로하지 않는로 다시 사용하지 않을 당신의 파일이므로 물론 두 번째 .tell()은 0 위치에 놓기 때문에 아무데도 움직이지 않았으므로 여전히 위치 0에있게됩니다.

+1

필드를 읽는 동안 줄을 어떻게 이동합니까? 양해 해 주셔서 감사합니다. –

+1

'didson_data' 변수에 이미 모든 행이 있습니다. 그러나 각각의 새로운 데이터 조각을 묘사하는 데 사용되는 개행 문자가있는 것처럼 보이지 않습니다. 당신이 * 데이터의 각 조각이 얼마나 많은 문자를 사용 하는지를 안다가'didson_data '의 조각을 사용할 것인지를 결정함으로써 줄을 따라 움직이는 것처럼 보입니다. 한 행에 실제로 데이터가 1 ​​개있는 경우 readlines() 메소드를 살펴볼 수 있습니다. – user1245262

+1

고맙습니다. –

0

전체 파일이 아닌 한 번에 모든 헤더를 계속 읽지 않는 이유는 무엇입니까? 그러면 파일은 헤더를 지나서 데이터 읽기를 시작할 준비가됩니다. 바로 frameinterval 헤더 다음에, 377 오프셋,

didson_data=didson_file.read(377) 

는 것을 할 것 진수의 위치를 ​​떠나 : 그냥하기

didson_data=didson_file.read() 

pos=didson_file.seek(0,0) 

: 그것은에서 read을 변경하는 것 같습니다.

작은 메모리를 절약하기 위해이 작업을 더 복잡하게 만들 필요가 없습니다.

가변 청크 파일의 나머지 부분을 읽고 사용자가있는 위치를 추적하는보다 일반적인 해결책은 사용자 고유의 기능을 사용하는 것입니다. 가능한 가장 큰 데이터 요소를 담을만큼 큰 크기의 파일을 읽을 수 있고, 데이터 요소의 실제 크기를 계산하고, 데이터 요소를 문자열로 저장하고, 함수가 시작될 때 파일의 수신 오프셋을 찾습니다. + 방금 검색 한 데이터 요소의 길이)를 입력 한 다음 데이터 요소 문자열을 반환합니다. 기본적으로

:

당신이 바로 헤더 과거를 탐색했습니다 그것은 널

while True: 
     the_thing = get_chunk(didson_file) 
     if not the_thing: # It's a Null--it's the end of the file 
      return 
     # process the_thing 
# End the program 

을 반환 할 때까지 헤더는 것입니다 과거 일단 다음 반복

def get_chunk(fileobject): 
    result = fileobject.read(1024) 
    if len(result) == 0: # End of file 
     return Null 
    ## Determine what this is = thing 
    fileobject.seek(fileobject.tell()-1024+len(thing) 
    return thing 

를 호출 할 것이다

어떻게 든 객체를 구문 분석하고 길이를 결정해야합니다. get_chunk 함수는 파이썬에서 다른 유형의 객체를 반환 할 수 있습니다. the_think의 유형을 살펴 봄으로써 the_thing * 섹션은 여러 종류의 데이터에 대해 서로 다른 작업을 수행 할 수 있습니다.


진정한 이진 파일의 경우 readlines 함수를 사용하지 않아야합니다. 데이터의 모든 줄 바꿈은 우발적이므로 파일을 분리하는 데 사용하지 않으려 고합니다. 그러나 readlines 함수를 살펴 보는 것은 좋은 방법입니다.하지만 복사하는 것보다는 복사하는 것에서 적응해야합니다. 저는 멋진 아이디어 인 생성 함수를 가정하고, 함수를 한 번의 호출에서 다음 호출까지 모든 종류의 상태를 기억할 수 있습니다. 그러나 파일에있는 위치 만 기억하면되므로 이런 종류의 작업이 효과적 일 수 있고 이해하는 것이 더 간단합니다 (그러나 시간 효율성은 약간 떨어짐).

+0

글쎄,이 파일은 테스트 파일 일뿐입니다. 우리가 사용하게 될 실제 파일 크기는 약 50MB이므로 훨씬 더 큽니다.내 다른 문제는 프레임 헤더가 시작되는 위치에 긍정적이지 않다는 것입니다. 파일 헤더 바로 뒤에 있다고 생각하지 않습니다. 실제 파일의 크기 때문에 나는 그것을 덩어리로 읽어야한다고 생각합니까? –

+0

50MB에서 시작하는 항목은 500에서 끝나기 쉽기 때문에 파일을 청크로 읽는 복잡성을 추가하는 것이 좋습니다. 어떤 식 으로든 파일에있는 위치를 추적하는 (file.seek (i + last)를 사용하여 나의 예제에서는) 하나의 함수에서 섹션을 구문 분석하고 청크의 처리를 메인 프로그램. 'readline'이 파일 위치를 추적하고 메인 프로그램이 행에서 작동하는 곳에서'readline'이 어떻게 작동하는지 그 종류의 일치합니다. –

0

파일이 바이너리 데이터이고, 단지 몇 메가 바이트가되는 경우, 모든 것을 한 번에 읽을 수 있습니다. 바로 didson_file.read()으로 지금하고있는 일입니다. 당신이 그 구조체를 가지고 있기 때문에 당신이 필요로하는, 사실

with open("my_file_name") as f: 
    for line in f: 
     do_something_with_line(line) 

: 파일이 라인으로 구성 텍스트 데이터 인 경우

, 당신이 사용할 수있는 좋은 관용구가 편리하게 한 번에 한 줄을 처리 할 수있다 파싱하려면 바이너리 파일을 읽는 것이 아주 분명합니다. 이 경우, 메모리 사용량에 문제가 없다면 모든 것을 버리고, 그렇지 않으면 청크로 읽어야합니다 (더 복잡하지만 메모리 사용량을 줄입니다).

관련 문제