题目要求:生成一个512M大小的文件(文件的内容不管),用什么方法速度最快.----------------------------------------------------
以下是本人的测试:代码1:
var FHandle:THandle;
begin
  self.FreeOnTerminate:=True;
  self.OnTerminate:=Form1.createSucc;
  FHandle:=CreateFile('testfile.wnd',
  GENERIC_READ or GENERIC_WRITE , 0, nil, CREATE_ALWAYS,
  FILE_FLAG_SEQUENTIAL_SCAN, 0);
  if FHandle=INVALID_HANDLE_VALUE then
    raise Exception.Create('创建文件失败');
  try
      SetFilePointer(FHandle,1024*1024*512,nil,FILE_CURRENT);
      if not SetEndOfFile(FHandle) then
        raise Exception.Create('设置文件大小失败');
  finally
    CloseHandle(FHandle);
  end;
end;
用时:15231毫秒
---------------------------------------------------
代码2:
var FileStream:TFilestream;
    buf:array[0..1023] of byte;
    i: integer;
Begin
  FileStream:=TFilestream.create('testfile.wnd',fmCreate);
  fillchar(buf,1024,'0');
  for i:=0 to 1024*512 do
    FileStream.Write(buf,1024);
  FileStream.Free;
  {
end;
用时:22332毫秒
--------------------------------------------------------
有兴趣的写出你的代码,并写出使用的时间.

解决方案 »

  1.   

    15秒会不会太长了点?我看bitcommet点了开始之后好像马上就分配了硬盘空间
      

  2.   

    var
      fh:integer;
    begin
      fh:=_lcreat('c:\temp',0);
      _llseek(fh,512*1024*1024,FILE_BEGIN);
      _lwrite(fh,nil,0);
      _lclose(fh);
    end
    ------------------
    13秒
    估计是我的机子速度快吧,估计快不了多少
      

  3.   

    var FileStream:TFilestream;
    Begin
      FileStream:=TFilestream.create('testfile.wnd',fmCreate);
      filestream.size:=512*1024*1024; 
      FileStream.Free;
      {
      

  4.   

    我还有一种方法可以创建  max(int64)GB 大小的文件用时比你们都小.
    不是吹牛.....
      

  5.   

    var
      F: HFILE;
    begin
      F := FileCreate('C:\Test.tmp', 0);
      SetFilePointer(F, 1024 * 1024 * 512, nil, FILE_BEGIN);
      SetEndOfFile(F);
      FileClose(F);
    end;
      

  6.   

    呵呵,当然不是吹牛,MSDN里都写的很清楚啊~~~Although the parameter lpDistanceToMoveHigh is used to manipulate huge files, the value of this parameter should be set when moving files of any size. If it is set to NULL, then lDistanceToMove has a maximum value of 2^31–2, or 2 gigabytes less two. This is because all file pointer values are signed values. Therefore if there is even a small chance that the file will grow to that size, you should treat the file as a huge file and work with 64-bit file pointers. With file compression on NTFS, and sparse files, it is possible to have files that are large even if the underlying volume is not very large.If lpDistanceToMoveHigh is not NULL, then lpDistanceToMoveHigh and lDistanceToMove form a single 64-bit signed value. The lDistanceToMove parameter is treated as the low-order 32 bits of the value, and lpDistanceToMoveHigh as the upper 32 bits. Thus, lpDistanceToMoveHigh is a sign extension of lDistanceToMove. To move the file pointer from zero to 2 gigabytes, lpDistanceToMoveHigh must be set to either NULL or a sign extension of lDistanceToMove. To move the pointer more than 2 gigabytes, use lpDistanceToMoveHigh and lDistanceToMove as a single 64-bit quantity. For example, to move in the range from 2 gigabytes to 4 gigabytes set the contents of lpDistanceToMoveHigh to zero, or to –1 for a negative sign extension of lDistanceToMove. To work with 64-bit file pointers, you can declare a LONG, treat it as the upper half of the 64-bit file pointer, and pass its address in lpDistanceToMoveHigh. This means you have to treat two different variables as a logical unit, which is error-prone. The problems can be ameliorated by using the LARGE_INTEGER structure to create a 64-bit value and passing the two 32-bit values by means of the appropriate elements of the union.It is conceptually simpler and better design to use a function to hide the interface to SetFilePointer. To do so, use something like this:
    __int64 myFileSeek (HANDLE hf, __int64 distance, DWORD MoveMethod)
    {
       LARGE_INTEGER li;   li.QuadPart = distance;   li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);   if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
       {
          li.QuadPart = -1;
       }   return li.QuadPart;
    }
      

  7.   

    上面的li.LowPart, &li.HighPart在Delphi里就是在Delphi里就是var
      Size: Int64;Int64Rec(Size).Lo, @Int64Rec(Size).Hi
      

  8.   

    呵呵,至少你上面用TFileStream就完全是一会事~~~只是直接调API,理论上效率会高那么一点点,当然一般忽略不计
      

  9.   

    ehom的方法用时14841,不信你自己试一下,不会差很多的.
    其实这段和我的代码1是差不多的.
      

  10.   

    用过bitcommet都知道,当他下载一个文件时,它会先生成一个和要下载的文件大小相同的临时文件.
    它生成的速度相当快.
    当上面的代码测试之后,似乎都没有办法达到要求,是为什么呢???//
      

  11.   

    terrytzq(边缘):
    为什么不把你的代码贴出来和大家共享呢.
      

  12.   

    如果是ntfs 5以上的文件系统,可以用sparse文件BOOL DeviceIoControl(
      (HANDLE) hDevice,            // handle to a file
      FSCTL_SET_SPARSE,            // dwIoControlCode
      NULL,                        // lpInBuffer
      0,                           // nInBufferSize
      NULL,                        // lpOutBuffer
      0,                           // nOutBufferSize
      (LPDWORD) lpBytesReturned,   // number of bytes returned
      (LPOVERLAPPED) lpOverlapped  // OVERLAPPED structure
    );然后设置文件尾就可以了procedure ForExample;
    var
      F: TFileStream;
      Dummy, FSFlags: DWORD;
    begin
      if GetVolumeInformation('C:\', nil, 0, nil, Dummy, FsFlags, nil, 0)
      and ((FSFlags and FILE_SUPPORTS_SPARSE_FILES) <> 0) then
      begin
        F := TFileStream.Create('C:\test.data', fmCreate);
        try
          DeviceIoControl(F.Handle, FSCTL_SET_SPARSE, nil, 0, nil, 0, Dummy, nil);
          F.Size := 1024*1024*512;
        finally
          F.Destroy();
        end;
      end;
    end;
      

  13.   

    原来你是用Fat32,那就没办法了~~~BitCommet能一次性生成和下载文件等大的空文件?其实那是错觉,刚开始文件大小只是0,然后逐步加大到和要下载文件等大的.
      

  14.   

    var
      F: HFILE;
    begin
      F := FileCreate('C:\Test.tmp', 0);
      SetFilePointer(F, 1024 * 1024 * 512, nil, FILE_BEGIN);
      SetEndOfFile(F);
      FileClose(F);
    end;
    --------------------------------------------------------------
      这个,速度快
      

  15.   

    FlashGet 如果设置“获得文件大小后立即申请磁盘空间”,那么就是生成一个和目标一样大的文件,如果没有设置就是逐步加大。而且申请空间(就是生成文件)速度也很快,1G的文件才几秒。一样期待代码中……
      

  16.   

    我的是FAT格式,时间几乎用在
    SetEndOfFile(F);这一个函数上。
      

  17.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      fs: TFileStream;
      b: Byte;
      timecnt: Integer;
    begin
      timecnt := GetTickCount();
      fs := TFileStream.Create('F:\ABCD.TST', fmCreate);
      fs.Position := 512*1024*1024-1;
      fs.Write(b, sizeof(b));
      fs.Free();
      timecnt := GetTickCount() - timecnt;
      Application.MessageBox(PChar('Use time: '+inttostr(timecnt)), 'OK', MB_OK);
    end;
    耗时如下
    FAT32:  11607
    未压缩的NTFS: 1.492
    压缩的NTFS: 0
      

  18.   

    上面写错了
    耗时如下
    FAT32:  11607
    未压缩的NTFS: 1492
    压缩的NTFS: 0
      

  19.   

    本质都是API做的直接访问FileSystem当然最快,但着实不容易实现http://lysoft.7u7.net
      

  20.   

    楼上说的
    直接访问filesystem当然很快了
      

  21.   

    以下这个代码是我试过最快的了:
    var hf:HFile;
    begin
      hf:= CreateFile('test.tmp', GENERIC_WRITE, FILE_SHARE_WRITE nil,CREATE_ALWAYS,      FILE_ATTRIBUTE_NORMAL, 0);
      SetFilePointer(hf, 1024*1024*512, nil, FILE_BEGIN);
      SetEndofFile(hf);
      FlushFileBuffers(hf);
    end;
    用时是100毫秒。
    原因是没有加入CloseHandle(hf),如果加入CloseHandle,则又回到上面那个速度了--十几秒钟。
      

  22.   

    不错,这正是我在大富翁论坛所贴的代码:function CreateTempFile(const FileName: string; FileSize: Integer): Integer;
    begin
      Result := CreateFile(PChar(FileName), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
      SetFilePointer(Result, FileSize, nil, FILE_BEGIN);
      SetEndofFile(Result);
      FlushFileBuffers(Result);
    end;但是当文件句柄关闭的时候(手工调用CloseHandle或者进程退出),还是要很长时间,
    因为这个时候会将内存中512M数据传到硬盘上.现在关键之所在,就是如何避免传输?
    不过,顺便说一句,如果是作下载程序的话,最终我们还是需要把有用数据传到硬盘的,
    所以,我觉得,可以通过上面这个函数返回的句柄操作文件,待下载完毕,再关闭句柄.
      

  23.   

    继续关注此题,欢迎大家来此讨论: http://www.delphibbs.com/delphibbs/dispq.asp?lid=2954938
      

  24.   

    对,上面那个代码是从刘麻子老兄得来的。希望有人发表高见。
    我的意思是围绕一个特定大小临时文件,用多线程的方法,将这个文件填充成要下载的文件。
    大家可以围绕这个问题讨论,就是有点像FastGet那样就对了。
      

  25.   

    家里adsl猫坏了,今天才看到,我试了一下closefile用了10秒钟