3

私はPythonの初心者です。私はむしろ深いところに投げ込まれました。少し背景があります。私たちが読んでいるファイルは、ソナーイメージングカメラからのものです。現時点では、日付、ファイル名、フレーム数、ビーム数など、ファイルに書き込まれた属性を読み込もうとしています。まず、FILEヘッダーを読みたいと思います。次に、フレームごとに、FRAMEヘッダーを読み取ります。ファイルヘッダーが中断したフレームヘッダーを読み込む必要があります...これを実行するには、seek()が必要だと思います。これが私が現在持っているコードで、ファイルヘッダーを読み取り(正常に実行され)、フレームヘッダーの情報が終了するところから開始します。

編集されたコード:

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()

「main」を実行すると、1行ずつ読み取ることができますか?1行に1つの値かどうかはわかりませんが、基本的にはバイトごとに調べて、どのヘッダー値がどこにあるかを調べました。

どんな助けでもいただければ幸いです!!

4

3 に答える 3

2

ファイルの内容全体をに読み込んでからdidson_data、ファイルハンドラーdidson_fileをゼロに戻します。すべてのフィールドを分割didson_dataし、ファイル内の行やチャンクをステップスルーしないため、二度と使用しないでください。.tell()位置0を探してからどこにも移動していないため、位置0のままになります。

于 2012-05-23T19:20:14.540 に答える
0

ファイル全体ではなく、ヘッダーだけを一度に読み続けてみませんか。これで、ファイルはヘッダーを超えてデータの読み取りを開始できるように配置されます。fromを変更するように見えますread

didson_data=didson_file.read()

pos=didson_file.seek(0,0)

ただ:

didson_data=didson_file.read(377)

これを行うのは、frameintervalヘッダーの直後の10進オフセット377の位置を残すことだけです。

非常に少ないメモリを節約するためにこれをより複雑にする理由はありません。

ファイルの残りの部分を可変チャンクで読み取り、現在地を追跡するためのより一般的な解決策は、独自の関数を使用することです。可能な限り最大のデータ要素を保持するのに十分なサイズのファイルを読み取り、データ要素の実際のサイズを把握し、データ要素を文字列に保存し、(関数の開始時にファイル内の着信オフセット)+(取得したばかりのデータ要素の長さ)、データ要素の文字列を返します。

基本的に:

ヘッダーを通り過ぎて、繰り返し呼び出すように求められます

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

Nullが返されるまで

 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

ヘッダーを通過したら、オブジェクトを何らかの方法で解析し、オブジェクトの長さを決定する方法が必要になります。get_chunk関数は、Pythonでさまざまなタイプのオブジェクトを返すことができます。the_thinkのタイプを確認するだけで、*#processthe_thing*セクションはさまざまな種類のデータに対してさまざまなことを実行できます。


真のバイナリファイルの場合、readlines関数は使用しないでください。データ内の改行は偶発的なものであるため、ファイルを分割するためにそれらを使用することは望ましくありません。ただし、readlines関数を確認するというアイデアは優れていますが、readlinesからコピーするのではなく、そこから学んだことを適応させる必要があります。私はそのジェネレーター関数を想定しています。これはクールなアイデアであり、関数の呼び出しから次の呼び出しまで、あらゆる種類の状態を記憶できます。ただし、ファイル内のどこにいるかを覚えておくだけでよいので、この種のことは機能し、理解しやすくなります(ただし、時間効率は少し低下します)。

于 2012-05-23T20:01:50.647 に答える
0

ファイルがバイナリデータであり、数メガバイトになるだけの場合は、すべてを一度に読み取ることをお勧めします。これはあなたが今していることですdidson_file.read()

ファイルが行に編成されたテキストデータである場合、一度に1行ずつ便利に処理するために使用できる優れたイディオムがあります。

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

実際、解析する必要のある構造体があるので、バイナリファイルを読み取っていることは明らかです。その場合は、全体を丸呑みにするか(メモリ使用量に問題がない場合)、チャンクで読み取る必要があります(より複雑ですが、メモリ使用量を抑えます)。

于 2012-05-23T20:34:32.187 に答える