例外処理を解消するには?

解決


3377  2004-07-23 04:51:34  No: 54070

あるファイル(myfile.txt)を読み込んで、strに保存をおこなうプログラムを
作成しているのですが、Debug Error!が出てしまうので質問します。
以下がソースコードです。

////////////////////

CString str;
CFile myFile("myfile.txt", CFile::modeRead);
CArchive arLoad(&myFile, CArchive::load);
arLoad >> str;
arLoad.Close();

/////////////////////

ビルドしてエラーは出ないのですが、実行するとデバックエラーで
abnormal program termination
となり、止まってしまいます。
デバックウインドには
例外処理 (初回) は test.exe (KERNEL32.DLL) にあります: 0xE06D7363: Microsoft C++ Exception。
と表示されています。
このエラーの解消方法、ご存知の方がいらっしゃったら教えてください。

CArchiveを使うのは始めてなので、ソースコード自体も間違ってるかもしれません。
それも含めてご指南願えたらうれしいです。
最終的にはファイルから一行ずつ読み込んでCString型のバッファーに格納したいと考えています。


シャノン  2004-07-23 05:15:09  No: 54071

まず、myfile.txt はありますか?
それと、CArchive で文字列を読み込む際は、その前の1バイト(だったか4バイトだったか忘れた)に、その文字列の長さが入っていたような気がします。
まず、CArchive を使ってファイルに文字列を書き出してみてください。

というか、CArchive で書き出したものだけを読むようにしないといけないと思うんですが。


3377  2004-07-23 06:09:41  No: 54072

CArchive を使った文字列の書き出しは正常にできました。
ファイルもできています。
そこで書き出したファイルを読み込もうとしても同じエラーが出てしまいます。

ソースコードは以下の通りです。

/////////////////
CFile myFile("myfile", CFile::modeCreate | CFile::modeReadWrite);
CString str1="aaa";
CArchive arStore(&myFile, CArchive::store);

arStore.WriteString( str1 );
arStore.WriteString( "\n" );
arStore.Close();

char ch[256];
CArchive arLoad(&myFile, CArchive::load);

arLoad.ReadString( ch, 255 );
arLoad.Close();

//////////////////////
よろしくお願いします。


シャノン  2004-07-23 06:45:43  No: 54073

こんなコードで成功しました。
はて、違うのはどこだ…?

    CString str = "もじゃらはなもげら";

    CFile outFile( "myfile.txt", CFile::modeWrite | CFile::modeCreate );

    CArchive serializer( &outFile, CArchive::store );
    serializer << str;
    serializer.Close();
    
    outFile.Close();

    CFile inFile( "myfile.txt", CFile::modeRead );

    CArchive deserializer( &inFile, CArchive::load );
    deserializer >> str;
    deserializer.Close();

    inFile.Close();

    std::cout << str << std::endl;


シャノン  2004-07-23 06:51:21  No: 54074

わかったわかった。
CArchive << なり WriteString なりで文字列を書き込んだ後、
ファイルポインタは書き込みが終了した位置、つまりファイル終端にあるのです。
そのまま、読み取りを行うと、終端から後ろにはデータがないからエラーが出るわけです。

というわけで、arStore.Close(); の後に

myFile.Flush(); // 書き込みを即座に反映させる
myFile.SeekToBegin(); // 次の読み込みは先頭から行わせる

の2行を追加すれば、きっと幸せになれるでしょう。


3377  2004-07-23 18:21:38  No: 54075

シャノンさん、ありがとうございました。
幸せになれました。

前おっしゃっていた
"CArchive で書き出したものだけを読むようにしないといけないと思うんですが。
というのは本当ですか?
同じソースコードでCArchive arStoreに関する部分を消して実行すると、
フフフフフフフフフ・・・・・
と表示されてしまいます。

既存のテキストファイルを一行ずつCString型バッファに取り込む方法って何かありますか?
ご存知だったら教えてください。


シャノン  2004-07-23 19:02:52  No: 54076

前にも書きましたが、CArchive からの文字列の読み込みは、それに先立って
何バイト読めばいいかを読み取っています。
つまり、ファイルには文字列の前にその長さが書き込まれていなければなりません。
そのため、正確には CArchive で文字列のみを書き出したファイルであっても、それはテキストファイルではなくバイナリファイルであるということになります。
また、CArchive での文字列の読み書きは必ずそのようになっているという保証もありません。
つまり、ひょっとしたら VC++ の次期バージョンでは NULL 終端文字列として書き込まれているかもしれませんし、何か他の方法で長さが書き込まれているかもしれません(まず無いとは思いますが、絶対に無いとは断言できません)。

で、既存のプレーンテキストファイルから一行ずつ読み込む方法ですが。
CStdioFile::Read / WriteString を使うのがよいのではないかと思われます。
お試しください。


3377  2004-07-24 01:59:32  No: 54077

なるほど、CArchiveは何バイト読めばいいかを指定しなければいけない仕様なのですね。わかりました。
CStdioFile::Read / WriteStringを用いたら、問題がすべて解決しました。
ファイルから一行ずつ読み込んでCString型のバッファーに格納する目標までクリアです。
シャノンさん本当にどうもありがとう。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加