2009-05-29 8 views
5

バイナリファイルを.NETにキャッシュし、キャッシュされたファイルに対して通常のファイル操作を実行できますか?C#でバイナリファイルをキャッシュする

+2

? 1)キャッシュ? 2)バイナリファイル(非テキストファイル、実行ファイル、イメージなど)? 3) "通常のファイル"操作ですか? –

+1

また、なぜキャッシュしますか?多分それは不要ですか? – uriDium

+0

ユーズケースをご利用ください。 –

答えて

11

これを行う方法は、FileStreamオブジェクトの内容全体をMemoryStreamオブジェクトに読み込み、このオブジェクトを後でI/Oに使用することです。どちらのタイプもStreamから継承されているため、使用法は実質的に同一になります。ここで

は例です:

private MemoryStream cachedStream; 

public void CacheFile(string fileName) 
{ 
    cachedStream = new MemoryStream(File.ReadAllBytes(fileName)); 
} 

だから、あなたが指定したファイルをキャッシュするときに一度CacheFileメソッドを呼び出し、その後、どこか他のコード使用cachedStreamで読み取ります。 (実際のファイルは、内容がキャッシュされるとすぐに閉じられます)。覚えておいていただきたいのは、終了した時点でcachedStreamを処分することだけです。

+3

+1:これは実際に尋問者が望んでいるかもしれないと思います。 –

+0

おそらく大丈夫でしょう - 私たちがGBまたは2のサイズを持つファイルについて話しているならば唯一の問題でしょう。 –

+2

ええ、この方法は、ファイルサイズがRAMのサイズに近づいたときには当然役に立ちません。しかし、その点ではデータベースサーバーを使用しているはずなので、ここでは問題にはならないと思います。 – Noldorin

3

最新のOSにはキャッシュシステムが組み込まれているので、実際にファイルとやりとりするたびに、ファイルのメモリ内キャッシュとやりとりしています。

カスタムキャッシュを適用する前に、重要な質問をする必要があります。基本となるファイルが変更されてキャッシュされたコピーが無効になるとどうなりますか?

キャッシュされたコピーを変更することができ、その変更を元のファイルに戻す必要がある場合は、問題をさらに複雑にする可能性があります。

ファイルが小さい場合は、別の回答で示唆しているようにMemoryStreamを使用する方が簡単です。

ファイルに変更を保存する必要がある場合は、すべてをMemoryStreamに転送するラッパークラスを作成できますが、書き込み操作が実行されるたびにtrueに設定されるIsDirtyプロパティも追加されています。その後、あなたが選択したときにいつでも(大きな取引の最後に)(IsDirty == true)をチェックして新しいバージョンをディスクに保存する管理コードを作成できます。変更はメモリ内で行われ、後でいつか保存されるため、これは「遅延書き込み」キャッシングと呼ばれます。

実際に問題を複雑にしたい場合や、ファイルサイズが非常に大きい場合は、独自のページングを実装して、バッファサイズ(1 MBの場合もあります)を選択して、その固定数のうちの小さい数のbyte[]ページを保持しますサイズ。今回は、各ページに汚れた旗があります。 Streamメソッドを実装して、呼び出し元から詳細を隠すようにし、必要に応じてページバッファを取得(または破棄)します。あなたは簡単に生活をしたい場合

最後に、試してみてください。

http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx

それはあなたがすべてはあなたのプロセスの内部で起こっての代わりに、経由して、SQL Serverのとしてではなく、ファイルに同じSQLエンジンを使用することができます外部RDBMSサーバー。これはおそらく、ファイルを照会して更新するもっと簡単な方法を提供し、手書きの永続コードがたくさん必要になることを避けます。

+0

それはメモリマップファイル(http://en.wikipedia.org/wiki/Memory-mapped_file)は何ですか?それでも、OPはできるだけ早くファイルハンドルを閉じたいと思っています。 – Noldorin

+0

ファイルのメモリマッピングでは、OSがファイル(任意のファイル)を使用して、プロセスのアドレス空間の領域に仮想メモリバッキングストアを提供します。 (ページファイルは、この目的を通常のメモリ割り当てに使用します。)OSにはファイルへのアクセス方法に関係なく動作するディスクキャッシュがあります。 grepなどを使って数百MBのテキストファイルを検索してみてください。もう一度やってみると、それはもっと速く起こりますし、ハードドライブはサウンドを作りません。 –

+0

@Ewwicker:うん、あなたが正しいと確信しています。それにもかかわらず、コンテンツをMemoryStreamにコピーすることは、a)ファイルのロックを維持しないため、ここでは最善の解決策であるように思われます。b)パフォーマンスの向上をもたらすと考えられます。 – Noldorin

3

もちろん、ファイルをバイト[]配列に読み込んで作業を開始することもできます。そして、あなたはあなたがのMemoryStreamにあなたのFileStreamをコピーして、それで作業を開始することができますストリームを使用する場合 - のように: - まあ、通常はビルドで異なるファイルのメカニズムを使用すると、パフォーマンスが心配な場合

public static void CopyStream(Stream input, Stream output) 
{ 
     var buffer = new byte[32768]; 
     int readBytes; 
     while((readBytes = input.Read(buffer, 0, buffer.Length)) > 0) 
     { 
       output.Write(buffer, 0, readBytes); 
     } 
} 

をアクセス方法で十分です。

0

私はあなたがやっている内容を正確に把握していないが、私はこの提案を提供します(これはよく、またはあなたがやっていることに応じて、実行可能ではないかもしれない):

の代わりにだけの内容をキャッシュファイルの内容を厳密に型指定された素敵なコレクションに入れてキャッシュしてみませんか?おそらく、項目の検索が少し楽になります。解析が必要ないため、処理が速くなります。

+0

ファイルには多くのレコードが含まれています。それは実際にmaxmind国のデータベースのバイナリファイル –

+0

です。それであなたが本当の問題は、あなたがあなたのクエリからあなたが望む性能を得ていないと仮定できるか? –

0

Luceneには、ディスクからメモリにバイトをキャッシュし、店舗などをインテリジェントに更新する非常に洗練されたキャッシュシステムがあります。そのコードを見て、どのように機能するかを知ることができます。また、MSSQLチームがより重要な実装の詳細についてかなり近づいているので、Microsoft SQL Serverのデータストレージレイヤーを読むこともできます。

関連する問題