CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
(图)邪恶的韩国UMPC 使用 Java 编写数据库应用新规范
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Delphi >  VCL组件开发及应用

谁的速度最快?

楼主linzhengqun(风。我回来了)2005-01-07 15:46:23 在 Delphi / VCL组件开发及应用 提问

题目要求:生成一个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毫秒  
  --------------------------------------------------------  
  有兴趣的写出你的代码,并写出使用的时间.  
  问题点数:70、回复次数:47Top

1 楼g961681(技术庸人(情商太低))回复于 2005-01-07 15:55:24 得分 0

scTop

2 楼cocosoft()回复于 2005-01-07 15:57:54 得分 0

测试Top

3 楼surpassable()回复于 2005-01-07 15:58:18 得分 0

gz~~~~  
  和搂主差不多Top

4 楼linzhengqun(风。我回来了)回复于 2005-01-07 16:00:47 得分 0

等待......  
  ^^Top

5 楼weidegong(weidegong)回复于 2005-01-07 16:09:51 得分 5

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

6 楼linzhengqun(风。我回来了)回复于 2005-01-07 16:17:57 得分 0

楼上太对了,我就是因为这个原因,所以才在这里发这个贴的.  
  期待精彩的代码Top

7 楼fansnaf(投币一元)回复于 2005-01-07 16:22:29 得分 0

kanfenTop

8 楼constantine(飘遥的安吉儿)回复于 2005-01-07 16:48:06 得分 0

gzTop

9 楼zxthello(万有斥力)回复于 2005-01-07 17:18:22 得分 0

gz,  
  学习!Top

10 楼lzy6204(为了忘却的记忆)回复于 2005-01-07 17:33:04 得分 10

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

11 楼terrytzq(边缘)回复于 2005-01-07 17:36:12 得分 5

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

12 楼terrytzq(边缘)回复于 2005-01-07 17:37:41 得分 0

用时不知道!  
  应该快吧。Top

13 楼terrytzq(边缘)回复于 2005-01-07 17:46:36 得分 0

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

14 楼ehom(?!)回复于 2005-01-07 17:55:28 得分 10

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

15 楼ehom(?!)回复于 2005-01-07 17:57:24 得分 0

时间太短,无法精确计算,十几毫秒到一百多豪秒均有可能,一般小于100Top

16 楼web700(*FS*的小狗腿子)回复于 2005-01-07 17:59:47 得分 0

学习.Top

17 楼ehom(?!)回复于 2005-01-07 18:03:15 得分 0

呵呵,当然不是吹牛,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;  
  }  
  Top

18 楼ehom(?!)回复于 2005-01-07 18:04:42 得分 0

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

19 楼terrytzq(边缘)回复于 2005-01-07 18:10:48 得分 0

我的不是这种方法。要简单多了Top

20 楼ehom(?!)回复于 2005-01-07 18:17:38 得分 0

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

21 楼ygflydream(飞飞)回复于 2005-01-07 18:24:46 得分 0

up!Top

22 楼linzhengqun(风。我回来了)回复于 2005-01-07 18:37:37 得分 0

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

23 楼linzhengqun(风。我回来了)回复于 2005-01-07 18:42:36 得分 0

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

24 楼linzhengqun(风。我回来了)回复于 2005-01-07 18:43:57 得分 0

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

25 楼alphax(豪言壮语的乌鸦)回复于 2005-01-07 18:54:27 得分 10

如果是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;  
  Top

26 楼alphax(豪言壮语的乌鸦)回复于 2005-01-07 18:57:03 得分 0

不过如果只是分配文件大小其实没有什么意义,因为如果实际提交的时候没有足够的磁盘空间,写操作也是失败的Top

27 楼ehom(?!)回复于 2005-01-07 19:03:26 得分 0

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

28 楼linzhengqun(风。我回来了)回复于 2005-01-07 19:18:51 得分 0

我认真看了一下,Bt在还没有连接成功时,它是0,但一旦连接成功后,它就突然变得和要下载的文件一样大了。  
  如果它是逐步加大,应该可以看到它正一步步变大才对,怎么能突然变得和下载文件一样大呢?  
  一直不懂。  
   
  Top

29 楼maming2003(關機.睡覺!)回复于 2005-01-07 19:19:49 得分 0

关注Top

30 楼maming2003(關機.睡覺!)回复于 2005-01-07 19:22:13 得分 0

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

31 楼Hozaka(空虚的狼)回复于 2005-01-08 09:10:11 得分 0

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

32 楼Hozaka(空虚的狼)回复于 2005-01-08 09:11:16 得分 0

另外,大家有没有想过,那10几秒的时间都用在什么地方了?哪里用掉的时间最多?我想可能对解决问题有帮助,哈哈~~  
   
  :)Top

33 楼linzhengqun(风。我回来了)回复于 2005-01-08 09:20:54 得分 0

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

34 楼linzhengqun(风。我回来了)回复于 2005-01-08 09:24:03 得分 0

如果没有办法,就能找会汇编了,对文件分配表进行操作Top

35 楼Hozaka(空虚的狼)回复于 2005-01-08 09:46:25 得分 0

我的意思就是楼上的意思,直接修改文件分配表,把结束标志划到指定的大小之后就可以了Top

36 楼linzhengqun(风。我回来了)回复于 2005-01-08 09:49:29 得分 0

去汇编版块问问。呵呵  
  希望有人既然讨论Top

37 楼ahjoe(强哥)回复于 2005-01-08 14:02:08 得分 10

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:   0Top

38 楼ahjoe(强哥)回复于 2005-01-08 14:03:39 得分 0

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

39 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2005-01-08 14:21:22 得分 0

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

40 楼Kshape(C/C++初学者~~~~)回复于 2005-01-08 15:10:54 得分 0

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

41 楼linzhengqun(风。我回来了)回复于 2005-01-09 10:08:04 得分 0

以下这个代码是我试过最快的了:  
  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,则又回到上面那个速度了--十几秒钟。  
   
  Top

42 楼liumazi(刘麻子)回复于 2005-01-09 11:10:20 得分 20

不错,这正是我在大富翁论坛所贴的代码:  
   
  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数据传到硬盘上.现在关键之所在,就是如何避免传输?  
  不过,顺便说一句,如果是作下载程序的话,最终我们还是需要把有用数据传到硬盘的,  
  所以,我觉得,可以通过上面这个函数返回的句柄操作文件,待下载完毕,再关闭句柄.Top

43 楼liumazi(刘麻子)回复于 2005-01-09 11:27:02 得分 0

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

44 楼lemon_wei(研究BT,做好P2P)回复于 2005-01-09 11:44:12 得分 0

关注Top

45 楼fsybaby(!报峰语)回复于 2005-01-09 11:50:47 得分 0

Guan   zhuTop

46 楼linzhengqun(风。我回来了)回复于 2005-01-09 12:40:01 得分 0

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

47 楼jinjazz(近身剪)回复于 2005-01-10 09:00:11 得分 0

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

相关问题

  • 加快速度?
  • 如何核对数据速度最快。
  • 看看那个速度最快
  • rh8.0哪里下载速度最快?
  • 怎样填充Image速度最快
  • adsl速度挺快!
  • 为什么dxdbgrid导出到excel的速度比dbgirdeh快?什么grid控件导出到excel的速度最快?
  • 用JAVA操作EXCEL时用什么最好,速度最快?
  • 如何以最快的速度从递归程序中跳出。。。。。。。。。。。。。。
  • 共享上网用什么好??要速度最快!!

关键词

  • 文件
  • 代码
  • 硬盘
  • 下载
  • timecnt
  • tfilestream
  • setendoffile
  • filestream
  • fhandle
  • setfilepointer

得分解答快速导航

  • 帖主:linzhengqun
  • weidegong
  • lzy6204
  • terrytzq
  • ehom
  • alphax
  • ahjoe
  • liumazi

相关链接

  • Delphi类图书
  • Delphi类源码下载
  • Delphi控件下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
惹火投票。。火热进行中...

社区焦点:

教你怎样用C#搞笑整人
最懒惰的程序员写的Cache
程序员如何掌握专业英语
Java栈与堆
分享:让人懊恼的面试
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo