重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【終了しました】教えて!gooアプリ版

お世話になります。
Visual Studio2005にてC++のプログラムを作成しており、プログラム内で作成したcsvファイルをプログラム起動時に読み込むような動作を行っております。
そこで、件名のとおりの症状が発生しております。
具体的な症状としましては、csvファイルをCFileのメンバ関数Read()で読み出しているのですが、ファイル内の特定の箇所を読み出そうとしたときに、例外エラーが発生し、エラー番号を確認したところCFileException::m_IOsErrorが”38”となっていました。
ネットで調べたところ、エラー番号38はEOFエラーらしいのですが、普通EOFが見つかったのであればCFile::Read()の場合例外エラーは発生しないかと思います。また、msdnで調べたところファイルを非同期で読み込んだ場合には発生するような事が記載されておりましたが、CFile::Open時に非同期指定にはしておらずデフォルトの指定でファイルを開いております。
また、件のcsvファイルをOS上でコピー&ペーストをしようとすると、「エラー番号38により、データがコピーができない」といった警告文が表示され、コピーすることも出来ません。
このcsvファイルが破損した為なのかな?とは思っているのですが、そのはっきりした原因がわからずどうしたものかとはまっております。
もし同じ症状にあわれた方、対処方法をご存じの方がいらっしゃいましたら、情報を提供頂ければと思っております。
よろしくお願い致します。

開発環境)
Windows CE 6.0
Visual Studio 2005

A 回答 (3件)

ということで…ちょっと試してみました。



VS2005で「MFC スマート デバイス アプリケーション」でソリューションを作成。
ダイアログスタイルにして、後は標準のまま。
# 対象はWindows Mobile 6 Professionalで。

ダイアログにボタンを2つ作ってそれぞれ下記のように。(インデントは全角スペースに換えてあります)

void Cqa7620250_wm60Dlg::OnBnClickedButton1()
{
 CFile CsvFile;
 char ReadBuff[64];
 BOOL fResult;

 fResult = CsvFile.Open(_T("\\My Documents\\csvtest1.csv"), CFile::modeNoTruncate | CFile::modeRead | CFile::shareDenyNone);
 if(fResult) {
  UINT ReadSize;

  do {
   FillMemory(ReadBuff, sizeof(ReadBuff), 0x00);
   ReadSize = CsvFile.Read(ReadBuff, 40);
  } while(ReadSize != 0);
  CsvFile.Close();
 }
}

void Cqa7620250_wm60Dlg::OnBnClickedButton2()
{
 CFile CsvFile;
 char ReadBuff[64];
 BOOL fResult;

 fResult = CsvFile.Open(_T("\\My Documents\\csvtest2.csv"), CFile::modeNoTruncate | CFile::modeRead | CFile::shareDenyNone);
 if(fResult) {
  UINT ReadSize;

  do {
   FillMemory(ReadBuff, sizeof(ReadBuff), 0x00);
   ReadSize = CsvFile.Read(ReadBuff, 40);
  } while(ReadSize != 0);
  CsvFile.Close();
 }
}

デバイスのマイドキュメント下にそれぞれファイルを作成して、
1行40バイト(38文字+改行コード)のASCIIファイルを。
3行で、csvtest1.csvは最終行にも改行を置いて、csvtest2.csvは最終行の改行はナシ。
} while(ReadSize != 0);
の行にブレークポイントを置いて実行。

どちらも例外は吐きませんでした。
# 最終行読み込んだ後はReadSizeが0になって返却されてループを抜けます。

う~~ん…何が問題なんですかねぇ……。
Microsoft Visual Studio 8\VC\ce\atlmfc\src\mfc\filecore.cppの
 if (!::ReadFile(m_hFile, lpBuf, nCount, &dwRead, NULL))
  CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
ってどういう状態の時に動くのやら……。
    • good
    • 0

>エラーのあった行が最終行のデータだった為、エラーのあった行の直後の行の読み出し確認にはCFile::Seek()を使用し、エラー行分(40B)シークしてデータの読み出しをしました。



最終行で改行があるか…とか問題になり……ますかね?
# 改行がなくて40バイトに満たない。とか…… もっともそれでも例外にはならないハズですが。

>エラー番号の38ですが、CFileException::mIOsErrorが38ということでGetLastError()の返りが38だと確認したわけではありません。

CE版のMFCのソースだと…GetLastError()の値をCFileExceptionでthrowしている感じ…ですけど……。

>この例外エラーが発生した状態でGetLastError()を読み出したところ、GetLastError()でのエラーが発生してしまい呼び出すことが出来ませんでした。

というのも変な状態ですね……。
# 間のどこかで別にSetLastError()された…とか???

>その位置がEOFだと考えその位置からさらにデータを読み出したところ特に例外が発生せず、読み出したデータ数が0となるだけだったので、例外が発生しないと記述致しました。

CFile::Read()の戻り値が0…ということになるんでしょうかね。
MFCは使っていないので、ソースを読んだ程度なのですが。
# CE版はさらにサブセットになりますしね……。

>CE 6.0のヘルプも調べたところ

5.9とか書いてしまいましたが5.0の間違いでした。
VS2005のMSDN ライブラリで検索すると…CE 5.0の方しか出てこないんですよね……
WM 6.5のSDK入っているのに……
# VS2005でWM6.5のプロジェクトからヘルプ呼べば出るかなぁ。

>PCでは0x1AがEOFと判断していたのに対し、CE機では0x1Aはそのままの数字としてよみこむことが出来ました。

0x1AがEOFになるのは……テキストモードで開いた場合ですよね?
CFileだと0x1AはEOF判定しなかったと思いますが。
CStdioFileでテキストモード指定した場合…かと思われますが、その辺りはどうなんでしょう…。
# 自宅帰らないとMFCのソースは確認できないです。

WindowsAPIのCreateFile()でファイルを扱っている場合、テキストモードとバイナリモードの区別はないハズなので…EOFの判定はファイルを最後まで読んだかどうか…くらいかと。

状態がいまいち不明…ですね。
手元のWM機だと…Hybrid W-ZERO3しかない…のですが……。
# リコリスがデータをcsvで持っていますが…1行のサイズが不定なんですよねぇ……。
# まぁ、1行40バイトの適当なcsvファイル作って試せばいいのでしょうけど。
# 仕事が忙しいので試せるかは別問題ですが。(今夜ならちょっと時間取れそうかな…)
    • good
    • 0

ファイルの特定の場所…ということならば、その周辺はどんなデータになっているんでしょう?



WindowsMobile6の(というかVS2005の?)MFCのCFile::Read()見る限りだと、
APIのReadFile()で読み込みに失敗した…というときのようですが……。
# で、そのときのGetLastError()が0x00000038…ということかと。

>普通EOFが見つかったのであればCFile::Read()の場合例外エラーは発生しないかと思います。

EOFの状態でCFile::Read()すると…例外になるかと思われますが。
ReadFile()APIが失敗しますので。

>また、msdnで調べたところファイルを非同期で読み込んだ場合には発生するような事が記載されておりましたが、CFile::Open時に非同期指定にはしておらずデフォルトの指定でファイルを開いております。

WindowsMobileでは非同期読み込みは非サポート…かと。
少なくともヘルプで参照できるCE5.9のドキュメントでは
>lpOverlapped
>[in] Unsupported; set to NULL.
です。
    • good
    • 0
この回答へのお礼

ご回答頂きましてありがとうございます。

>ファイルの特定の場所…ということならば、その周辺はどんなデータになっているんでしょう?
今回作成しているcsvファイルは1行あたり40バイトの列のデータとなっており、読み込みエラーが発生する行以外の直前、直後の行は問題なくデータを読み出すことが出来ました。エラーのあった行が最終行のデータだった為、エラーのあった行の直後の行の読み出し確認にはCFile::Seek()を使用し、エラー行分(40B)シークしてデータの読み出しをしました。

># で、そのときのGetLastError()が0x00000038…ということかと。
エラー番号の38ですが、CFileException::mIOsErrorが38ということでGetLastError()の返りが38だと確認したわけではありません。というのも、この例外エラーが発生した状態でGetLastError()を読み出したところ、GetLastError()でのエラーが発生してしまい呼び出すことが出来ませんでした。

>EOFの状態でCFile::Read()すると…例外になるかと思われますが。
>ReadFile()APIが失敗しますので。
PC、CE組み込み機どちらでもEOFまでCFile::Read()を読み出したところ、EOFまで読み出した場合には引数の読み出したいデータ数と、返り値の読み出したデータ数が異なるようになり、その位置がEOFだと考えその位置からさらにデータを読み出したところ特に例外が発生せず、読み出したデータ数が0となるだけだったので、例外が発生しないと記述致しました。

>WindowsMobileでは非同期読み込みは非サポート…かと。
CE 6.0のヘルプも調べたところ、同じく非同期読み込みは対応していないとのことでした。申し訳ございませんでした。

PCとCE機で同じサンプルファイルを読み込んでテストしたところ、PCでは0x1AがEOFと判断していたのに対し、CE機では0x1Aはそのままの数字としてよみこむことが出来ました。CEでのEOFコードというのはどのような値なのでしょうね。。

お礼日時:2012/08/01 10:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています