2015-09-23 24 views
6

大きなバイナリファイルを読み書きする必要があります。私はBLOCK_SIZEと呼んでいますが、好きな、あるいは最適なバイト数がありますか?read()は一度に必要ですか?大きなバイナリファイルを読み書きするときのブロックサイズ

1バイトは確かに少しです。私はRAMに4GBを読み込むことは良いアイデアだとは思っていません - 「最高の」ブロックサイズですか?それともファイルシステム(私はext4上にある)に依存していますか?私は何を考慮する必要がありますか?

python's open()はさらにbuffering引数を提供します。私もそれを微調整する必要がありますか?

これは2つのファイルin-0.datain-1.dataout.dataに結合するサンプルコードです(現実には、手元にある質問とは無関係の処理が増えています)。 BLOCK_SIZEbufferingのデフォルトであるように思われio.DEFAULT_BUFFER_SIZEに等しくなるように選択される:

from pathlib import Path 
from functools import partial 

DATA_PATH = Path(__file__).parent/'../data/' 

out_path = DATA_PATH/'out.data' 
in_paths = (DATA_PATH/'in-0.data', DATA_PATH/'in-1.data') 

BLOCK_SIZE = 8192 

def process(data): 
    pass 

with out_path.open('wb') as out_file: 
    for in_path in in_paths: 
     with in_path.open('rb') as in_file: 
      for data in iter(partial(in_file.read, BLOCK_SIZE), b''): 
       process(data) 
       out_file.write(data) 
#   while True: 
#    data = in_file.read(BLOCK_SIZE) 
#    if not data: 
#     break 
#    process(data) 
#    out_file.write(data) 
+0

これには確かな回答はありません。問題のマシンのOS、ファイルシステム、物理ディスクに依存している可能性があります。これが汎用的なソリューションであることを意図している場合は、最良の答えを計算するためのパラメータをシステムに問い合わせるコードを追加することができます。 – cdkMoose

+0

私は 'io.DEFAULT_BUFFER_SIZE'を使って 'システムに質問しました'と思っていましたが、実際にはこのすべての詳細についての経験はありません。 –

+1

このシステムでも静的な回答はありません。これは、多数の変数に依存しますが、そのうちのいくつかは時間とともに変化したり、毎回異なったりする可能性があります。あなたのプログラムやシステムが他に何をしているのかが分かります。最善の方法は、一定の不変の代表的なテストファイルを使用して、その時点で適切なサイズを決定するために何かを書くことです。また、スタンドアロンテストを作成して一度実行して、見積もりを行い、アプリケーションにハードコードすることもできます(または、テストをインストールまたはセットアッププロセスの一部にすることもできます)。 – martineau

答えて

4

は、OSがあなたのために決定を作ってみましょう。

https://docs.python.org/3.4/library/mmap.html

それはRAMにファイルの内容をマッピングするために使用しているOSの基本的なメモリマッピングメカニズムを使用しています:のmmapモジュールを使用してください。

32ビットPythonを使用している場合は2GBのファイルサイズに制限があるので、このルートに進むには64ビットバージョンを使用してください。例えば

:あなたは任意の読み込み()関数を呼び出すと、RAMに持ち込むためにどのように多くのバイト数を決めなければならなかったことはありません

f1 = open('input_file', 'r+b') 
m1 = mmap.mmap(f1.fileno(), 0) 
f2 = open('out_file', 'a+b') # out_file must be >0 bytes on windows 
m2 = mmap.mmap(f2.fileno(), 0) 
m2.resize(len(m1)) 
m2[:] = m1 # copy input_file to out_file 
m2.flush() # flush results 

注意。この例では、あるファイルを別のファイルにコピーするだけですが、あなたの例で述べたように、間に必要な処理を行うことができます。ファイル全体がRAMのアドレス空間にマップされていても、そこに実際にコピーされたわけではありません。 OSの裁量で、区分的にコピーされます。

+0

もし私が正しく理解していれば、まだバイト数を決める必要があるでしょう。[read([n]) '](https://docs.python.org/3.4/library/) mmap.html#mmap.mmap.read)。私は元の問題に戻ります。何が欠けていますか? –

+0

私は今、いくつかのコードを試していますが、本質的にmmapは、ファイルインタフェースに加えて、あなたのデータへのバイラルインターフェイスを提供します。あたかもそれがbytearrayにあったかのように、データにアクセスしたり、処理したりすることができます。 –

+0

私は「bytearray」からどのように利益を得ますか?私の 'data'は' '型のものです。これは私が必要とするものに対してはまったく問題ありません。しかし、私はこれがどこに行くのか見てみたい! –

関連する問題