如何快速清零文件内容?

时间:2011-04-22 15:10:27

标签: delphi

我想终止用户从我的程序中选择的文件。我写了这个示例代码:

var
  aFile: TFileStream;
Const
  FileAddr: String = 'H:\Akon.mp3';
  Buf: Byte = 0;
begin
  if FileExists(FileAddr) then
  begin
    // Open given file in file stream & rewrite it
    aFile:= TFileStream.Create(FileAddr, fmOpenReadWrite);
    try
      aFile.Seek(0, soFromBeginning);
      while aFile.Position <> aFile.Size do
        aFile.Write(Buf, 1);
    finally
      aFile.Free;
      ShowMessage('Finish');
    end;
  end;
end;

如您所见,我用0(null)值覆盖给定文件。此代码可以正常工作,但在大文件中速度非常低。我想在多线程代码中执行此过程,但我尝试了一些测试代码而无法执行此操作。例如,我创建了4个执行此操作的线程来加速此过程。

有没有办法加快这个过程?

5 个答案:

答案 0 :(得分:4)

我不知道它是否可以帮助你,但我认为你可以做得更好(比多线程)写入更大的缓冲区。
例如,您可以初始化16k宽的缓冲区并直接写入FileStream;你只需要检查文件的最后一部分,你只为其写入完整缓冲区的一部分 相信我,它会更快......

答案 1 :(得分:4)

好的,我会咬人:

const
  FileAddr: String = 'H:\Akon.mp3';
var
  aFile: TFileStream;
  Buf: array[0..1023] of Byte;
  Remaining, NumBytes: Integer;
begin
  if FileExists(FileAddr) then
  begin
    // Open given file in file stream & rewrite it
    aFile:= TFileStream.Create(FileAddr, fmOpenReadWrite);
    try
      FillChar(Buf, SizeOf(Buf), 0);
      Remaining := aFile.Size;
      while Remaining > 0 do begin
        NumBytes := SizeOf(Buf);
        if NumBytes < Remaining then
          NumBytes := Remaining;      
        aFile.WriteBuffer(Buf, NumBytes);
        Dec(Remaining, NumBytes);
      end;
    finally
      aFile.Free;
      ShowMessage('Finish');
    end;
  end;
end;

答案 2 :(得分:3)

多线程在这里不会帮到你。您的约束是磁盘访问,主要是因为您一次只写1个字节。

Buf声明为字节数组,并使用FillCharZeroMemory对其进行初始化。然后按如下方式更改while循环:

while ((aFile.Position + SizeOf(Buf)) < aFile.Size) do
begin
  aFile.Write(Buf, SizeOf(Buf));
end;
if (aFile.Position < aFile.Size) then
begin
  aFile.Write(Buf, aFile.Size - aFile.Position);
end;

答案 3 :(得分:2)

你应该从以上代码的缓慢中学习:

  1. 一次写一个字节是最慢和最差的方法,你会产生巨大的开销,并降低整体性能。

  2. 即使一次写1k字节(1024字节),也会有很大的改进,但写一个更大的数量当然会更快,直到你达到收益递减点,我猜是将介于200k和500k之间的写缓冲区大小。了解应用程序停止运行的唯一方法是进行测试,测试和测试。

  3. 经常检查位置与大小是完全多余的。如果您读取一次大小并写入正确的字节数,则使用本地变量可以节省更多开销,并提高性能。即,Inc(LPosition,BufSize)增加LPosition:整数逻辑变量,按缓冲区大小量BufSize。

答案 4 :(得分:0)

不确定这是否符合您的要求,但它有效并且速度很快。

var
  aFile: TFileStream;
const
  FileAddr: String = 'H:\Akon.mp3';
begin
  if FileExists(FileAddr) then
  begin
    aFile:= TFileStream.Create(FileAddr, fmOpenReadWrite);
    try
      afile.Size := 0;
    finally
      aFile.Free;
      ShowMessage('Finish');
    end;
  end;
end;

所以这些内容(在函数外声明b将改善循环中的性能,尤其是在处理大文件时)。我假设在应用filename中将是var

const
  b: byte=0;
procedure MyProc;
var
  aFile: TFileStream;
  Buf: array of byte;
  len: integer;
  FileAddr: String;
begin
  FileAddr := 'C:\testURL.txt';
  if FileExists(FileAddr) then
  begin
    aFile := TFileStream.Create(FileAddr, fmcreate);
    try
      len := afile.Size;
      setlength(buf, len);
      fillchar(buf[0], len, b);
      aFile.Position := 0;
      aFile.Write(buf, len);
    finally
      aFile.Free;
      ShowMessage('Finish');
    end;
  end;
end;