- 締切済み
大きなファイルの読み書き
WindowsXP + SDKにてC++の開発をしています。 ディスクから50MB程度のファイルを読んで処理を施しまた書き戻すという事をやっていますが HANDLE handle; char fileName[256]; strcpy(fileName , "ファイル名"); handle = CreateFile(fileName , GENERIC_READ , NULL , NULL , OPEN_EXISTING , FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL ,NULL); としてファイルのオープンには成功するのですが OVERLAPPED ol; unsigned long size; unsigned long readSize; unsigned char *mem; ReadFile(handle , mem , readSize , &size , &ol) としていざ読もうとすると "ERROR_NO_SYSTEM_RESOURCES"が戻ってきて処理がとまってしまいます。 今までまったく同じコードで1~12MB程度のファイルは問題なく読み書き出来ていたのですが50Mのファイルを扱おうとしたところ問題が発生してしまいました。 FILE_FLAG_NO_BUFFERING と FILE_FLAG_OVERLAPPEDをはずすと読めるのですが余りにもアクセスが遅いので使い物になりません。 何か回避方法がありましたら御教授願います。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- machongola
- ベストアンサー率60% (434/720)
こんばんは。 100Mbyte位のファイルで試して見たのですが、確かに上手くいきません(手法が悪いのかもしれません)。 容量が大きくて、其れでいて可能な限り高速と言うのですから、恐らくDirect??系で映像や音像を流すのかな、と思います。 当方は使用した事が無いのですが、メモリマップドファイルが処方箋と成るかもしれません。 http://msdn.microsoft.com/ja-jp/library/cc430039.aspx
- chie65536(@chie65535)
- ベストアンサー率44% (8755/19868)
>としていざ読もうとすると >"ERROR_NO_SYSTEM_RESOURCES"が戻ってきて処理がとまってしまいます。 バッファリング無しでオーバーラップさせるには、指定する読み込みバッファに、必要なだけの実メモリが確保されていなければなりません。 この読み込みバッファは、スワップアウトされたり、メモリマネージャにガベージコレクトされたりして移動しない必要がありますので「ReadFileの呼び出し時に、指定しただけの物理的な空きメモリ」が必要です。 もし、空きメモリが無いのであれば、メモリ(つまりリソース)が足りないので、ERROR_NO_SYSTEM_RESOURCESでエラーになって当たり前です。 >OVERLAPPED ol; >unsigned long size; >unsigned long readSize; >unsigned char *mem; >ReadFile(handle , mem , readSize , &size , &ol) memとreadSizeが未初期化ですが、本当にこれで動いてますか? >FILE_FLAG_NO_BUFFERING と FILE_FLAG_OVERLAPPEDをはずすと読めるのですが余りにもアクセスが遅いので使い物になりません。 最低限必要なだけのメモリを確保して、そして、そのメモリをFixedステートメントでガベージコレクションされないようにして、読み書きを繰り返す。 「一気に全部読んで、処理して、一気に全部書いて」と言うのは非現実的。 もし「読み込んだサイズ」が「実メモリの実装サイズを遥かに超えるサイズ」の場合、仮想メモリと実メモリのスワップが多発し、膨大な量のディスクアクセスが発生します。 この時「プログラムでアクセスしているドライブ装置」と「仮想メモリをスワップしているドライブ装置」が同一の場合、同一ドライブ装置へのアクセスが集中し「まるでフリーズしたかのような速度」になります(シーク&リード、シーク&ライトが激しく頻発します) 「一気に全部読んで」が必要なのは、例えば「ファイルに書かれた内容により、どこをどう書き換えるかが決まり、常にランダムにアクセスする必要がある時」だけです。 普通は「先頭から、特定のブロック単位で、読んで書いてを繰り返す」で済む筈です。アルゴリズムを考え直す必要があるでしょう。 普通「ある一瞬、瞬間的に、ファイル内のすべてのデータが見えてないと処理出来ない」って事は有り得ない筈です。 場合によっては「処理上、前後256キロバイトのデータが見えてないと処理できない」って事はあるかも知れませんが、その場合は512キロバイトのバッファがあれば済みます。 もし「ある一瞬、瞬間的に、ファイル内のすべてのデータが見えてないと処理出来ない」のなら、処理ルーチンの設計ミスです。処理ルーチンを作り直しましょう。
- nda23
- ベストアンサー率54% (777/1415)
先ず、一度に全データを読み込む必然性は何ですか? データの安全性を考えると、Aファイル→メモリ→Aファイルでは 危険です。メモリ→Aファイルの最中に障害が起きたらどうする のでしょう?安全性、再実行性を考えると、以下の流れでしょうか。 Aファイル→メモリ→Bファイル→BからAへCopy→Bを削除 別に1レコード(掲題の例では256か?)ずつ処理しても良いのでは? それともミリ秒を争うというような要求があるのでしょうか?
お礼
回答ありがとうございます。 画像の連番ファイルを読み出して画面に表示・再生させています。 今まで2048x1556を最大としていましたが4096x3112サイズのファイルを扱うことになった為に引っかかってしまいました。 このサイズのファイルをリアルタイムで再生することはかなり難しいのは承知していますが、少しでも高速に表示をしたいというのが理由です。