Ç言語初心者です。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;
}
No.4ベストアンサー
- 回答日時:
アルゴリズムを替えてみましょう。
基本的に方向性を示しただけですから、エラー処理等は
別途考慮してください。
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をクローズする。
かなり早くなると思いますよ。
以上です。
No.3
- 回答日時:
まずどこに時間がかかっているのかをきちんと把握する必要はあるな.
まあ #2 で言われているように, 「printf をなくす」と速くなることは確実. ただ, 「10 GB のファイルを作る」となると必然的に時間はかかるので「ある程度」であきらめざるをえない.
あと, fread の返り値を使えばわざわざファイルサイズを調べておく必要はなくなるし, ループが簡単になるので結果的に (ちょっとだけ) 速くなるはず.
No.2
- 回答日時:
>printf( "%d番目\n", i );
>printf( "\n" );
このあたりのprintf関数の呼び出しは、実行時間を増大させるもとです。
思い切ってカットしてみてはどうでしょう。
ループについては、今のままでもいいし、別の回答者さんが書かれているような方法でもいいです。
同じ結果を得るためのコードは何通りもあるっていうだけです。
No.1
- 回答日時:
・ファイルサイズに64bitの型を使う
・1文字ずつではなく、ある程度まとめて読み書きする。
> while(1)
> {
> i++;
> // 指定サイズになったら終了
> if(i > MEGA * SIZE) break;
わざわざ無限ループ+breakなんてことしないで、普通にforとか whileの中で判定とかすればいいんじゃないですか?
この回答への補足
回答ありがとうございます。
無限ループにしたところに意味はなかったのですが、処理スピードに違いが出るのでしょうか?
まとめて読み書きすることも考えたのですが、変更後のファイルサイズを小さい単位で指定する時に不便が生じるのではないかと思い1文字ずつ読み込むことにしました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
printf による16進表示について
-
空白を含んだ文字列がうまく格...
-
C言語で複数列のデータを1列の...
-
リストの作成と出力(C言語)
-
char型2つを結合し、short型に...
-
C言語のプログラムで、途中で止...
-
タイムカードのシステムを作り...
-
バイナリファイル(画像)のよみ...
-
なぜ無限ループになるかが分か...
-
矢印キーを押下してコンソール...
-
WinInetのInternetOpenUrl関数...
-
プログラミングの授業の課題です
-
10個出力で改行したいのですが...
-
2÷3などの余りについて
-
複数桁10進数の*桁目だけを抽出...
-
マイナスからプラスへ転じた時...
-
*をユーザーが入力した数字の数...
-
2の補数を計算するプログラム
-
fgetsなどのときのstdinのバッ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
C言語で複数列のデータを1列の...
-
#defineが使用するメモリ領域に...
-
printf による16進表示について
-
空白を含んだ文字列がうまく格...
-
C言語のプログラムで、途中で止...
-
プログラミングの授業の課題です
-
char型2つを結合し、short型に...
-
C言語でのCSVファイルの読み出...
-
矢印キーを押下してコンソール...
-
【C言語】全角文字の配列を、全...
-
エラーについて質問です。
-
リストの作成と出力(C言語)
-
[C]セグメンテーションエラー:...
-
バイナリファイル(画像)のよみ...
-
WinInetのInternetOpenUrl関数...
-
受信データから必要な部分のみ...
-
c言語で文書を読み込み、単語の...
-
VC++でSQLへSELECT文を送ったの...
-
reallocでエラー
おすすめ情報