2013-01-09 11 views
11

私はmatlabスクリプトをnumpyに変換していますが、バイナリファイルからデータを読み込む際にいくつか問題があります。ファイルfromfileを使用してファイルの先頭をスキップすると、fseekに相当しますか?これは私がする必要がある抽出のタイプです:numpyでバイナリファイルの一部を読み取る方法は?

fid = fopen(fname); 
fseek(fid, 8, 'bof'); 
second = fread(fid, 1, 'schar'); 
fseek(fid, 100, 'bof'); 
total_cycles = fread(fid, 1, 'uint32', 0, 'l'); 
start_cycle = fread(fid, 1, 'uint32', 0, 'l'); 

ありがとう!

答えて

19

あなたは、通常の方法でファイルオブジェクトを求め、その後、fromfileにこのファイルオブジェクトを使用して使用することができます。ここでは完全な例です:

import numpy as np 
import os 

data = np.arange(100, dtype=np.int) 
data.tofile("temp") # save the data 

f = open("temp", "rb") # reopen the file 
f.seek(256, os.SEEK_SET) # seek 

x = np.fromfile(f, dtype=np.int) # read the data into numpy 
print x 
# [64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 
# 89 90 91 92 93 94 95 96 97 98 99] 
+1

ダン、ファイル名の代わりにファイルオブジェクト!これはまさに私が探しているものです、これはfromfileのドキュメントに追加する必要があります...ありがとう! – brorfred

3

は、おそらくより良い答えがある...しかし、私はこの問題に直面してきたとき、私は私に、この問題に対する簡単な解決策を与えた私はすでに個別の異なる部分にアクセスしたいファイルを、持っていました。

たとえば、たとえば、chunkyfoo.binは、6バイトのヘッダー、1024バイトのnumpyアレイ、およびもう1つの1024バイトのnumpyアレイで構成されるファイルです。 numpy.fromfileは最初に0に戻るlseekであるため、ファイルを開いて6バイトを検索することはできません。しかし、あなたはちょうどmmapファイルをすることができますし、代わりにfromstringを使用します。これは、あなたがしたい正確に何のように聞こえる

with open('chunkyfoo.bin', 'rb') as f: 
    with closing(mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ)) as m: 
     a1 = np.fromstring(m[6:1030]) 
     a2 = np.fromstring(m[1030:]) 

。実際の生活の中でa1a2にオフセットと長さは、おそらくかなりのコメントを固定されているよりも、ヘッダに依存していることを、もちろん、除きます。

ヘッダーはちょうどm[:6]であり、structモジュールを使用して明示的に引き離すか、またはreadデータを使用して解析することができます。しかし、mを構築する前にseekreadからfに明示的にseekとをコールすることもできます。a1a2に影響することなく動作します。

class SeekedFileWrapper(object): 
    def __init__(self, fileobj): 
     self.fileobj = fileobj 
     self.offset = fileobj.tell() 
    def seek(self, offset, whence=0): 
     if whence == 0: 
      offset += self.offset 
     return self.fileobj.seek(offset, whence) 
    # ... delegate everything else unchanged 

私は「変わらない他のすべてを委任する」でしたことにより、このよう

私は別の非numpy関連のプロジェクトのためにやったの代替は、ラッパーファイルオブジェクトを作成することです、建設時間に属性のlistを生成し、それを__getattr__で使用していますが、おそらく何かよりハッキリではありません。 numpyは、ファイルのようなオブジェクトのメソッドのほんの一例にしか依存せず、正しく文書化されていると思いますので、明示的にそれらを委譲してください。しかし、私はあなたが明示的seekベースのコードの束の上にポートを機械的にしようとしている場合を除きmmapソリューションは、こちらより理にかなっていると思います。 (mmapnumpy.arrayの代わりにnumpy.memmapのままにしておくこともできます。numpyはページングなどの制御をより多く制御できますが、実際にはnumpy.memmapmmapを取得するのはかなりトリッキーです一緒に仕事をする。)

+1

誰でもこれを控えめにした理由を説明してください。 – abarnert

+0

古いスレッドですが、fromfileはファイル内のファイル位置から読み取ります。この機械の多くは不要で、numpy.fromfileよりも遅くなります。 – noobermin

1

これは私が異種バイナリファイルに任意読まなければならないとき、私は何をすべきかです。
numpyのアレイのdtypeを変化させることによりarbitray方法でビットパターンを解釈することを可能にします。 問題のMATLABコードはcharと2 uint読み込みます。

このpaperを読むと、配列のdtype、stride、dimensionalityを変更することで何が達成できるのかについて、ユーザーレベルで簡単に読むことができます。

import numpy as np 

data = np.arange(10, dtype=np.int) 
data.tofile('f') 

x = np.fromfile('f', dtype='u1') 
print x.size 
# 40 

second = x[8] 
print 'second', second 
# second 2 

total_cycles = x[8:12] 
print 'total_cycles', total_cycles 
total_cycles.dtype = np.dtype('u4') 
print 'total_cycles', total_cycles 
# total_cycles [2 0 0 0]  !endianness 
# total_cycles [2] 

start_cycle = x[12:16] 
start_cycle.dtype = np.dtype('u4') 
print 'start_cycle', start_cycle 
# start_cycle [3] 

x.dtype = np.dtype('u4') 
print 'x', x 
# x [0 1 2 3 4 5 6 7 8 9] 

x[3] = 423 
print 'start_cycle', start_cycle 
# start_cycle [423] 
関連する問題