大容量(10MB〜900MB)のファイルを物理的に別のドライブにコピーをするには
CopyFile関数だとPCが固まったようになります。
ですから バイナリで読み書きをしてやってるんですが、もっと早くなる方法はないんでしょうか?
以下コード
var
ReadFileBuff,WriteFileBuff:TFileStream;
ReadFileSize:Integer;
BuffArr:array[0..4095] of Byte;
begin
ReadFileBuff:= TFileStream.Create('C:\Test\Test.aaa', fmOpenRead);
WriteFileBuff:=
TFileStream.Create('G:\TestDir\Test2.aaa', fmCreate);
repeat
Application.ProcessMessages;
ReadFileSize:= ReadFileBuff.Read(BuffArr, SizeOf(BuffArr));
WriteFileBuff.Write(BuffArr, ReadFileSize);
until ReadFileSize<>SizeOf(BuffArr);
ReadFileBuff.Free;
WriteFileBuff.Free;
よろしくお願いします。
>CopyFile関数だとPCが固まったようになります。
メッセージ処理ができませんからね。スレッドをつくって CopyFile() したらいいんでは。
早くする=固まらないようにする、ではありませんよ。
それを踏まえて、早くしたいと言うことであれば
1.ファイル全てをメモリに格納
2.一気に書き出し。
で早くなると思います。もっとも、ハード面で、
・メモリ量を多くする(900MBであれば、OSに512MB取られたと考えて、1.5〜2GB程度でしょう)
・メモリ読み書き速度を速くする
・HDDの読み書き速度を速くする(ハード的には、ここが一番のネックです)
・CPUの処理速度を速くする
ということも必要となります。
固まらないようにするには、「処理を遅くする」必要があります。
りりかさんの言うように、メッセージ処理が出来ないため、固まったようになっているので、書き込み中定期的にメッセージ処理すればよろしいかと。
APIのSHFileOperation関数を使うと、エクスプローラでのファイルコピーと同じようなダイアログが出せるので、固まったようには見えません。
りりかさん、にしのさん レスありがとうございます。
実は、SHFileOperationは考えてみたんですが、ダイアログの表示は自分で作ったほうが速度的に速くなるのではと思い、候補からはずしました。
実際に速度の計測はしていないんですが…。
>1.ファイル全てをメモリに格納
>2.一気に書き出し。
メモリに格納とは、読みながら書き出しではなく一発で読み込んで書き出すということで理解していいんでしょうか?それとも、他に何か方法があるんでしょうか?
よろしかったらその辺を詳しく教えてもらえないでしょうか。
コード進行というか、考え方というか 最初に書いたコードで考え方的に間違いなのかというのも知りたいです。トンチンカンなことをしているのであればご指摘をお願いします。
ちなみに Application.ProcessMessages;のあとに処理状況を確認できるように ProgressBarを使っています。
一発読み込み、一発書き出し、で合っています。
読みながら書き出す場合、同HDDだとヘッダの移動が増えるため遅くなります。
最初に書いたコードは、基本的には合ってますよ。ただ、速度向上のみ取るのであれば、他の更新を止めてでもコピー作業を優先した方が早いです。
そうすると固まったようになるんですがね。
ファイルのコピーでネックとなるのは、HDDへのアクセスです。
どうしてもここがボトルネックとなります。
何かを犠牲にしないとダメですよ。
コピーしながら他の作業をしたいのであれば、りりかさんのいうようにスレッド化しておいた方が良いです。
にしのさん ありがとうございます。
やはり、一発読み込みは速いですね。
今回は、自分用なので一発読み込みでいこうと思います。
しかし、これじゃあ他は何もできないので使いもんにはなりません(笑
PCをほったらかしにしといて、その間にやらせるようにしようと思います。
ただ、りりかさんがおっしゃてたスレッド化のほうもしてみようと思います。
ありがとうございました。
ツイート | ![]() |