C言語でのファイル書き込みと読み込み不都合

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ABA

C言語でのファイル書き込みと読み込み不都合

#1

投稿記事 by ABA » 2年前

MS VCでファイルの書き込み文を実行直後、すぐ読み込みをすると、
前回書き込んだファイルのデータが読み込んでしましました。
(直前の書き込みが途中であるためか)

これまで自分の想像ではC言語の関数が書き込んでから、はじめて次の文に行くとしましたが、実際そうでないと実証しました。

さて、どうすれば、直前の書き込み完成してから、直後の読み込みを実行することができるのでしょうか。
今直前の書き込みの直後にSleep()を取っています。

ただし、sleepの時間が短すぎだと、効かないし、長すぎると時間的にもったいない。

良い方法があれば、是非教えてください!

たいちう
記事: 418
登録日時: 8年前

Re: C言語でのファイル書き込みと読み込み不都合

#2

投稿記事 by たいちう » 2年前

うまくいかないというプログラムを載せてください。
(file closeしてないとか?)

アバター
みけCAT
記事: 6198
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: C言語でのファイル書き込みと読み込み不都合

#3

投稿記事 by みけCAT » 2年前

fflush関数を用いると、ファイルへの書き込みを完了させることができます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: C言語でのファイル書き込みと読み込み不都合

#4

投稿記事 by かずま » 2年前

ABA さんが書きました: これまで自分の想像ではC言語の関数が書き込んでから、はじめて次の文に行くとしましたが、実際そうでないと実証しました。
その実証が間違っていないことを実証してください。
ABA さんが書きました: さて、どうすれば、直前の書き込み完成してから、直後の読み込みを実行することができるのでしょうか。

コード:

#include <stdio.h>

int main(void)
{
	char buf[1024];
	FILE *fin, *fout;
	fout = fopen("a.txt", "w");
	if (fout == NULL) { puts("can't create b.txt"); return 2; }
	fin = fopen("a.txt", "r");
	if (fin == NULL) { puts("can't open a.txt"); return 1; }
	fputs("abcdefg\n", fout);  // または fprintf(fout, "abcdefg\n");
	fflush(fout);              // これがあるとないとで大違い
	if (fgets(buf, sizeof buf, fin) != NULL)
		fputs(buf, stdout);
	else
		printf("can't read a line\n");
	fclose(fout);
	fclose(fin);
	return 0;
}
書式による書き込み fprintf、
文字列書き込み fputs、
1文字書き込み fputc、
指定バイト数書き込み fwrite、
これらは、バッファリングしているバッファへの書き込みであり、
実際のファイルへの書き込みは、バッファがいっぱいになった時に
自動的に行われます。
したがって、書き込んだつもりでも、ファイルに本当に書き込みが
完了しているとは限りません。
fflush があると、バッファリングしているデータをすべてファイルに
書き込みます。
fclose もバッファリングしているデータをすべてファイルに書き
込んでから、ファイルをクローズします。

ABA

Re: C言語でのファイル書き込みと読み込み不都合

#5

投稿記事 by ABA » 2年前

皆様
いろいろアイディア心より感謝致します。
再度fopen()や繰り返しfclose fflush(NULL)いろいろさんざんに試しましたが、
やはり、読み込みが可笑しいーーー直前のファイル内容でなく、もう一つ前の内容みたいですね。
実例:

コード:

cv::imwrite(imageFileName, m1);// Mat m1.
FILE* fp = fopen(imageFileName,"r"); 
//↑ or fopen(imageFileName,"rb");いずれも成功
//以下はfpに対する読み込みと画像データ解析――直前の画像データでなく、古いデータであるのは分かった。これに関して可視化されたので、間違いないのです。
また宜しくお願い致します。

かずま

Re: C言語でのファイル書き込みと読み込み不都合

#6

投稿記事 by かずま » 2年前

ABA さんが書きました:

コード:

cv::imwrite(imageFileName, m1);// Mat m1.
FILE* fp = fopen(imageFileName,"r"); 
//↑ or fopen(imageFileName,"rb");いずれも成功
//以下はfpに対する読み込みと画像データ解析――直前の画像データでなく、古いデータであるのは分かった。これに関して可視化されたので、間違いないのです。
これは「C言語でのファイルの書き込み」ではありません。
最初から間違った情報を出して質問しても、適切な回答は得られませんよ。
「OpenCV の C++ でのファイルの書き込み」となぜ書かなかったのですか?

cv::imwrite の返却値が true か false かを調べてください。

m1 が壊れているかなんかで、imwrite がファイルを作成できないことが
考えられます。試しに、imageFileName のファイルを削除してから、
実行するとどうなりますか?
imwrite がファイルを作成しないと、fopen も失敗するはずです。
古いデータはありません。

ABA

Re: C言語でのファイル書き込みと読み込み不都合

#7

投稿記事 by ABA » 2年前

かずま様
お返答ありがとうございます。
cv::imwrite(imageFileName, m1);// Mat m1.
自体が問題ないと考えられます。
その後のfopen()がきちんとできますし、
imwriteから返した値がempty()にならなかったのです。

なんといっても、このトッピを出した時に申し上げたように、
cv::imwrite(imageFileName, m1);// Mat m1.
の後ろに
Sleep(1000);
を置けば、以降まったく正常な画像データを読み込めます。

どう理解すれば良いのでしょうか。

朱鷺

Re: C言語でのファイル書き込みと読み込み不都合

#8

投稿記事 by 朱鷺 » 2年前

可能性の1つですが、
ABA さんが書きました: cv::imwrite(imageFileName, m1);// Mat m1.
の後ろに
Sleep(1000);
を置けば、以降まったく正常な画像データを読み込めます。
という動きをしているのであれば、バッファキャッシュやディスクキャッシュによる影響が考えられます。
imwriteによる書き込み後直ちにfopenでファイルを開こうとした際、ディスク上のファイル(データ)をオープンする。
→imwriteで書き込んだデータはまだキャッシュ上からフラッシュされていないため古いデータが読み込まれる。

Sleepを入れることで正常なデータが読み込まれたのは、単に時間経過でメモリ上のデータがフラッシュされただけとか。

ABA

Re: C言語でのファイル書き込みと読み込み不都合

#9

投稿記事 by ABA » 2年前

具体実例コーダまで書いていただいた方に本当に感謝の気持ちいっぱいです。

原因の推測はともかくとして、これまでファイル書き込みと読み込みの間、
Sleep関数を入れなければならないという経験がないし、聞いた事もないですね。

そのSleep関数の時間が気になります。

回避方法があれば、いつでもお教えいただければ幸いです。


 [[未解決]]

朱鷺

Re: C言語でのファイル書き込みと読み込み不都合

#10

投稿記事 by 朱鷺 » 2年前

OpenCVの知識は全くないので直接的な回答はできませんが。
ABA さんが書きました: 原因の推測はともかくとして、これまでファイル書き込みと読み込みの間、
Sleep関数を入れなければならないという経験がないし、聞いた事もないですね。
キャッシュが絡む話としては特に珍しくないように思います。

対処法はimwriteによる書き込み後にバッファキャッシュをフラッシュする、またはimwriteによる書き込みを
ダイレクトアクセス(バッファキャッシュを使用せずに書き込む)とすればよいと思いますが、その方法がわかりません、申し訳ありません。

そもそも書き込み直後にファイルをオープンするという処理もどうなのかなぁとも思いますが。

結城紬
記事: 42
登録日時: 2年前

Re: C言語でのファイル書き込みと読み込み不都合

#11

投稿記事 by 結城紬 » 2年前

確かに imwrite が完了したときにはファイルをクローズしているはずなので、おかしいですね。
Sleep を使っているということは Windows だと思いますが、具体的な実行環境は何でしょうか。
また、 imageFileName で書き込んでいるファイル名・拡張子(画像形式)と、書き込み先の場所(ドライブ・種類など)は何ですか。
あと、アンチウィルスソフトなどは使っていますか。

sleep

Re: C言語でのファイル書き込みと読み込み不都合

#12

投稿記事 by sleep » 2年前

imwrite がやっていることは、C言語の標準ライブラリ関数を使用してバイナリ形式でファイルを開いて書き込んでファイルを閉じているだけです。


バージョンの記載が無いので、3.2 を対象とします。

imwrite は fopen(..., "wb") でファイルを開き、関数を終了する前に fclose でファイルを閉じます。
戻り値の型は bool です。fopen(..., "wb") に失敗した場合 false を返します。それ以外はtrueを返します。

imwrite は、独自でバッファリングしながら以下のタイミングで fwrite を実行します。
fwrite を実行する WBaseStream::writeBlock を呼び出すタイミングは以下の2パターンです。
 1.fopen(..., "wb") が成功した状態(m_is_opened が true)で、fclose を実行する WBaseStream::close を呼び出したとき
 2.バッファに書き込まれたデータサイズが BS_DEF_BLOCK_SIZE (1<<15) 以上になったとき
このとき、バッファに書き込まれたデータサイズが 0 でなければ fwrite が実行されます。

imwrite は fclose の戻り値を確認してません。(fclose が成功しても失敗しても ファイルディスクリプタを保持している変数に 0 を代入し、imwrite は true を返します)
fclose の失敗を考慮するなら、WBaseStream::close() で実行されているので、確認用のコードを追記して観測するのも手です。
(むしろ、何か事象が発生していればイベントビューアで ETW による書き込みを確認できるので、もし問題が発生していれば何が起きているかを知ることができます)


とりあえず、
確認せずに自論で結果を決めてしまったり、自分しか観測していない状況証拠だけで他者に結論を求めてみたり、話が浮ついていて要領を得ていないので、再現性があり誰でも事象を観測できる動作可能なコードをまずは載せてみてください。
その上で質問された方が早期に解決できるのではないかと思います。

sleep

Re: C言語でのファイル書き込みと読み込み不都合

#13

投稿記事 by sleep » 2年前

オフトピック
気づかれた方もいらっしゃるかもしれませんが、大筋は同じなので説明は1つのEncoderに絞ってあります。
最初にfcloseの動作から疑うのは定理を疑うようなもので手順としては少しナンセンスなので、特定環境のみなのか、特定Encoderのみなのか、特定ファイルのみなのか、などいくつか先に切り分けしておいた方が良いと考えます。

ABA

Re: C言語でのファイル書き込みと読み込み不都合

#14

投稿記事 by ABA » 2年前

sleep様
情報ありがとうございます。
自分はなぜかdebug状態でも
imwrite()関数の中身にジャンプできなかったんです。

ご提供の情報に基づいて、さらに確認します。
成果あればご報告させていただきます。

=========
追加情報
OS Windows10
環境 Visualstudio2015
Sleep() windowsのものです。

返信

“C言語何でも質問掲示板” へ戻る