ページ 11

fwriteで漏れ無くデータを書き込む方法

Posted: 2012年9月23日(日) 22:12
by shiro4ao
こんばんは。
ある程度大きなデータをファイルへ書きだそうと思ったのですが。
下記コードの方法1で書き込むと書き込まれないデータがちょくちょく出てきました。
(奇数サイズになると1バイト書き込まれないのが原因だと思います)
そこで方法2のように書き込みサイズが奇数か偶数かで分けて書き込んでみると
全くデタラメでおかしいデータが書き込まれてしまいました。

本来であればfwrite(buf,size,1,fp);とすればいいのですが、
そうすると書き込みブロックが大きいせいなのか、1回のfwriteなのに
やたらと処理に時間がかかります。

どうすればいいでしょうか。

コード:


	FILE *fp;
	char buf[極めて大きい];
	int size;

	//方法1
	fwrite(buf,size/2,2,fp);
	//方法1ここまで


	//方法2
	fwrite(&buf[0],1,size/2,fp);
	if(size%2==1){
		fwrite(&buf[size/2],1,size/2+1,fp);
	}else{
		fwrite(&buf[size/2],1,size/2,fp);
	}
	//方法2ここまで


	fclose(fp);		
	return ret;


Re: fwriteで漏れ無くデータを書き込む方法

Posted: 2012年9月23日(日) 22:17
by box
shiro4ao さんが書きました: 下記コードの方法1で書き込むと書き込まれないデータがちょくちょく出てきました。
(奇数サイズになると1バイト書き込まれないのが原因だと思います)
おそらく、おっしゃるとおりの理由だと思います。
shiro4ao さんが書きました:

コード:

	//方法2
	fwrite(&buf[0],1,size/2,fp);
	if(size%2==1){
		fwrite(&buf[size],1,size/2+1,fp);
	}else{
		fwrite(&buf[size],1,size/2,fp);
	}
	//方法2ここまで
奇数・偶数で場合分けした際の書き込む基点がbuf[size]である理由は何でしょうか。
buf[]の定義範囲外を指しているように思えてなりません。

で、そういう工夫をしたところで、書き込む大きさが結局sizeバイトであることには変わらないので、
工夫の結果がいい方向に出るかどうかはちょっと怪しいような気がします。

Re: fwriteで漏れ無くデータを書き込む方法

Posted: 2012年9月23日(日) 22:30
by shiro4ao
最初のfwriteでsizeバイト書き込んであるので、sizeバイトぶん進んだ位置から書き始めないと
データが重複すると思ったからです。

具体的には
buf="abcdefghi"ならsize=9なので、最初に書き込むのはsize/2の4バイト(abcd)
残りがefghiなので先頭のaから数えてsize/2バイト目から書き込むべきだと思ったからです。




追記
すみません。間違えていました。
おっしゃるとおり、bufの範囲外を指定していました。正しくは
&buf[size/2]を指定するべきでした。

最初の投稿の部分も修正しておきます。

コード:

	//方法2
	fwrite(&buf[0],1,size/2,fp);
	if(size%2==1){
		fwrite(&buf[size/2],1,size/2+1,fp);
	}else{
		fwrite(&buf[size/2],1,size/2,fp);
	}
	//方法2ここまで


Re: fwriteで漏れ無くデータを書き込む方法

Posted: 2012年9月23日(日) 22:57
by shiro4ao
何度も投稿すみません。
先ほどの、方法2でうまくデータが書き込まれたことを確認しました。

なぜ1まとまりで書き込むと時間が異常にかかるのかはわかりませんが、
なんとか漏れ無く書き込めたのでこれにて解決とさせて頂きます。
ありがとうございました。

Re: fwriteで漏れ無くデータを書き込む方法

Posted: 2012年9月23日(日) 23:06
by かずま
方法3

コード:

    int n = fwrite(buf, 1, size / 2, fp);
    fwrite(buf + n, 1, size - n, fp);

Re: fwriteで漏れ無くデータを書き込む方法

Posted: 2012年9月24日(月) 06:43
by shiro4ao
方法3のが一番スマートですね。
戻り値が書き込んだ数を教えてくれるんでした