アプリ版:「スタンプのみでお礼する」機能のリリースについて

Ç言語初心者です。visualstudio2010を使用しています。

ファイルサイズ100MBのtest.binをバイナリモードで開き、10GBになるまで0を追加するプログラムを組みたいと思います。
ファイルを読み込んで出力するようには組めたのですが、この手法だとファイルサイズが大きいと時間がかかってしまいます。

現在のソースは以下の様になっているのですが、どうしたらもっと早く終わらせることが出来るでしょうか?
また、int型でファイルサイズを取得していますが、ファイルサイズがもっと大きくなったときにint型では足りなくなってしまうのもどうすればいいのか困っています。
※元ファイルサイズ(test.bin)は例としています。今後?GBサイズになると思います。変更後のファイルサイズは今後10GBくらいまでで考えています。

#include <stdio.h>
#include <string.h>
#include "stdafx.h"

#define KIRO (1024)
#define MEGA (KIRO*1024)
#define GIGA (MEGA*1024)
#define SIZE (100)

int main(void)
{
FILE *fp,*fpw;
unsigned char c;
unsigned char zero = 0;
int i = 0;
int filesize;

// 元ファイルをバイナリモードで開く
fp = fopen( "test.bin", "rb" );
if( fp == NULL )
{
printf( "test.binが開けません" );
return 1;
}

fseek( fp, 0, SEEK_END );
filesize = ftell( fp );
fseek( fp, 0, SEEK_SET );

// 書込み先をバイナリモードで開く
fpw = fopen( "test_W.bin", "wb" );
if( fp == NULL )
{
printf( "test_W.binが開けません" );
return 1;
}

while(1)
{
i++;
// 指定サイズになったら終了
if(i > MEGA * SIZE) break;

// ファイルサイズまで読み書き
if(filesize < i){
// 残りを0で代入
fwrite(&zero, sizeof(unsigned char), 1, fpw);/* 1文字ずつ書き込み */
}else{
// ファイルの内容を1文字ずつ読み書き
fread( &c, sizeof(unsigned char), 1, fp );/* 1文字ずつ読み込み */
fwrite(&c, sizeof(unsigned char), 1, fpw);/* 1文字ずつ書き込み */
}
printf( "%d番目\n", i );
}

printf( "\n" );

fclose(fp);
fclose(fpw);

return 0;
}

A 回答 (5件)

アルゴリズムを替えてみましょう。




基本的に方向性を示しただけですから、エラー処理等は
 別途考慮してください。


1. test.binをtest_W.binにコピーする。
※ 色々方法は有りますが例えば、
Win32のCopyFile関数でコピーする。

CopyFile( "test.bin", "test_W.bin", TRUE又はFALSE );

リファレンスはググるか、MSDN等で調べてください。

2. test_W.binをオープンし、ファイル末尾までシークする。

3. ファイルサイズが10GB未満の間、ゼロを追加する。
※ 1MB程度のバッファを用意してゼロクリアしておき
MB単位でストリームに書き込んだほうが良いでしょう。(w)

4. test_W.binをクローズする。


かなり早くなると思いますよ。

以上です。

この回答への補足

回答有り難うございます。

回答頂いたことを参考に組みなおしてみたいと思います。

補足日時:2011/04/16 18:37
    • good
    • 0

おっと, よく見たら「Ç言語」なのか. そんな言語, はじめて聞いた....

    • good
    • 0

まずどこに時間がかかっているのかをきちんと把握する必要はあるな.


まあ #2 で言われているように, 「printf をなくす」と速くなることは確実. ただ, 「10 GB のファイルを作る」となると必然的に時間はかかるので「ある程度」であきらめざるをえない.

あと, fread の返り値を使えばわざわざファイルサイズを調べておく必要はなくなるし, ループが簡単になるので結果的に (ちょっとだけ) 速くなるはず.

この回答への補足

回答有り難うございます。
ご指摘いただいた点を参考に見直させていただきます。

補足日時:2011/04/16 18:35
    • good
    • 0

>printf( "%d番目\n", i );


>printf( "\n" );

このあたりのprintf関数の呼び出しは、実行時間を増大させるもとです。
思い切ってカットしてみてはどうでしょう。

ループについては、今のままでもいいし、別の回答者さんが書かれているような方法でもいいです。
同じ結果を得るためのコードは何通りもあるっていうだけです。
    • good
    • 0

・ファイルサイズに64bitの型を使う


・1文字ずつではなく、ある程度まとめて読み書きする。

> while(1)
> {
> i++;
> // 指定サイズになったら終了
> if(i > MEGA * SIZE) break;

わざわざ無限ループ+breakなんてことしないで、普通にforとか whileの中で判定とかすればいいんじゃないですか?

この回答への補足

回答ありがとうございます。

無限ループにしたところに意味はなかったのですが、処理スピードに違いが出るのでしょうか?
まとめて読み書きすることも考えたのですが、変更後のファイルサイズを小さい単位で指定する時に不便が生じるのではないかと思い1文字ずつ読み込むことにしました。

補足日時:2011/04/15 19:58
    • good
    • 0

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