2011-06-23 7 views
6

ファイルからブロックを読み取ろうとしていますが、問題があります。バッファを使用して不明なサイズのファイルから読み取る

char* inputBuffer = new char[blockSize] 
while (inputFile.read(inputBuffer, blockSize)) { 
    int i = inputFile.gcount(); 
//Do stuff 
} 

は、私たちのブロックサイズが1024 bytesあるとし、かつファイルが24,3 KiBです。 23ブロック目を読んだら、読み返したのは0,3 KiBです。私はまた、0,3 KiBを読むことを望んでいます。実際にはgcount()を使用していますので、バッファのどれがどれくらいか分かりました。read(...)(それが少ない場合)
しかし、24番目のブロックにアクセスするとき、read(...)は、ファイル内の残りの未読バイトのサイズがバッファサイズより小さいため、プログラムがループに入り込まないような値を返します。私は何をすべきか?

答えて

3

他の回答へのコメントでお話するコンラッド・ルドルフは、eofまでの読書の問題点をよく指摘してくれると思います。あなたが何か他のエラーのためにeofに到達しないなら、あなたは無限ループにいます。だから彼のアドバイスを取るが、それを修正してあなたが特定した問題に対処する。これを行う1つの方法は次のとおりです。

bool okay=true; 
while (okay) { 
    okay = inputFile.read(inputBuffer, blockSize); 
    int i = inputFile.gcount(); 
    if(i) { 
     //Do stuff 
    } 
} 

編集:私の答えは受け入れられているので、できるだけ有用であるように編集しています。それは私のブール大丈夫は非常に不必要であることが判明(ferosekhanjの答えを参照してください)。 inputFileの値を直接テストする方が良いです。それは、ファイルが正常に開かれなかった場合にループに入るのをエレガントに回避できるという利点もあります。だから私はこれがこの問題の標準的な解決策だと思う。

inputFile.open("test.txt", ios::binary); 
while (inputFile) { 
    inputFile.read(inputBuffer, blockSize); 
    int i = inputFile.gcount(); 
    if(i) { 
     //Do stuff 
    } 
} 

は今、あなたがものを行う//最後の時間は、私は、ファイルが複数のblockSizeのバイトの長さであることを起こる場合を除いて、のblockSizeよりも少なくなります。

コンラッドルドルフの回答hereでも良いですが、.gcount()はループ外で一度しか呼び出されませんが、重複を避けるためにデータ処理を別の関数に入れる必要があるという欠点があります。

+0

"okay = inputFile.read(...)"の後にif(okay)を含めて、プログラムが無効なデータで動作しないようにする必要があります。私はこれを受け入れられた答えとしてマークします。 – Erandros

+0

@Erandos、それはあなたが正方形1に戻っているので動作しません - あなたは最後のサブブロックを処理しません!代わりにif(i)を追加すると、データがある場合にのみ実行します。 –

+0

あなたはそうです。私はまだ "if(lessThanBufferSizeFlag)"があるはずだと思います。私はどのようにフラグ値を取得するか分からない。 – Erandros

1

しかし、24番目のブロックにアクセスするとき、read(...)は、ファイル内の残りの未読バイトのサイズがバッファよりも小さいため、プログラムがループに入り込まないような値を返しますサイズ。

あなたのループが間違っているためです。あなたはやるべきこと:

while(!inputFile) { 
    std::streamsize numBytes = inputFile.readsome(inputBuffer, blockSize); 
//Do stuff 
} 

お知らせ​​代わりにreadの使用を。

+0

ループが間違っていますか?この100Kの担当者は、反対に言っています:http://stackoverflow.com/questions/6444876/c-reading-buffer-size/6444962#6444962私はそのreadomeを試してみましょう。 – Erandros

+1

@Erandros:彼はまた、whileの条件の中に読書を置くことは、「読みやすく」なっていると言います。これは私がコンテストするものです。実際の作業を行う条件ステートメントは、C/C++で確立されたイディオムであるかもしれませんが、必ずしも良好で読みやすいものではありません。 –

+0

私は "より読みやすい"問題に同意します。しかし、もし私が読み込みをして失敗するとどうなりますか?私は破損したデータで物事を続けます。それが起こらないことを確実にすることは、その最中にあった。 – Erandros

3

@Konrad Rudolphの解決策は、ストリームオブジェクト自体をチェックすることです。これには、eofおよびエラー状態のチェックが含まれます。 inputFile.readは()あなたが

while(inputFile.read()) 

のように書くことができます。しかし、これは常に動作しませんので、それ自体INPUTFILEあるストリームを返します。それが失敗する場合はあなたの場合です。適切な解決策は、私は、これは@Konradルドルフは彼のポストに何を意味するか解決策だったと思う

char* inputBuffer = new char[blockSize] 
while (inputFile) 
{ 
    inputFile.read(inputBuffer, blockSize); 
    int count = inputFile.gcount(); 
    //Access the buffer until count bytes 
    //Do stuff 
} 

以下のように書くことであろう。私の古いCPPの経験から、私も上記のようなことをするでしょう。

+0

これも機能します。 – Erandros

+0

私は実際に同意します。これは私の解決策よりも改善されています。 –

+0

私の解決策があなたよりも優れている点は、ループの後で 'gcount'を1回だけチェックする必要があることです(ループ内では常に' blockSize'と等しくなります)。そして、たとえ安価であっても、私は本当に不必要な操作を嫌っています。つまり、あなたのソリューションは、バッファの処理が重要でなくなるとすぐに優れています(= 1つのステートメント以上)。 –

関連する問題