至今无人能解. 有什么办法可以让程序在瞬间建立一个大小为 800MB 的磁盘文件, 但是不写任何内容进去?

twgdh 2006-09-15 11:50:30
就想 NetAnts 等下载软件所做的那样?
...全文
669 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
土著巫师 2006-09-21
  • 打赏
  • 举报
回复
chsize可能为了兼容C,做了一些数据流缓冲上的处理,所以影响了速度,没找到源码。(WINDOWS平台上按理说也是调用SetFilePosition),因为lseek就是调用了这个函数。
土著巫师 2006-09-21
  • 打赏
  • 举报
回复
1、网络蚂蚁用的也是CreateFile + SetFilePosition。(在一个磁盘空间不足的盘符里存贮你要下载的大文件,它会报错,提示:SetFilePosition返回失败。(以前偶尔发现的)
2、TFileStream在建立文件和改变文件大小时也是用的CreateFile + SetFilePosition(有源码可查)
3、上面两者从你的测试数据上看也是可以佐证的。(没什么区别。)
4、chsize函数按说不会有这么大的差异。奇怪。:(
mango279 2006-09-21
  • 打赏
  • 举报
回复
boyla(土著巫师) ( ) 信誉:99 Blog 2006-9-21 13:36:46 得分: 1
去看看我的这个问题:
http://community.csdn.net/Expert/topic/5038/5038640.xml?temp=.8979914
「已注销」 2006-09-21
  • 打赏
  • 举报
回复
mark
netliuming 2006-09-21
  • 打赏
  • 举报
回复
mark!!!!!!!!
土著巫师 2006-09-21
  • 打赏
  • 举报
回复
TO mango279(木目):

Button1Click函数里的部分可以抽取独立出来的,只有一句:Memo1->Lines->Add(End-Begin);是BCB专有的东西,其余部分可以在VC或其它IDE环境编译里,不会有问题的。
mango279 2006-09-21
  • 打赏
  • 举报
回复
boyla(土著巫师) ( ) 信誉:99 Blog
--------------------------------------------
没用过BCB,不知道对不对。
但在这里祝贺你下岗9个月,解脱了,解脱即超脱。不知道我们这些俗人何时才能解脱!
土著巫师 2006-09-21
  • 打赏
  • 举报
回复
正解:

0、WINDOWS API SDK 函数不是SetFilePosition(错),是SetFilePointer(对)。

1、BCB在WINDOWS平台上的I/O,最终都是调用WINDOWS API SDK函数,比如建立文件用CreateFile,读取用ReadFile,写入用WriteFile,关闭文件用CloseHandle,包括文件移动、改变大小等等。(这就是做操作系统的优势,所以其它开发商注定要比M$矮一节)。

2、BCB/DELPHI里的ANSI C/C++ 等函数fopen,fwrite, fread以及其它如lseek(其本质就是调用SetFilePointer这个SDK函数)等等函数或VCL文件的I/O统统都不例外。

3、重点说一下chsize这个函数,这个函数可以实现的很快的,慢的原因是BORLAND具体实现时,它首先记录下利用SDK函数GetFileSize得到的文件原大小,如果文件是增大时,它在改变文件大小后,再把文件扩大部分调用WriteFile API函数全部写上0x00,而且每次调用只写入128个字节的0x00, 所以要调用N多次写入函数,加上磁盘输出本来就很慢,所以很慢就可想而知了 :( 而通过SDK扩大时,扩大部分的内容是不可知的。(随机数据,分配的扇区里原来是什么就是什么,删除其它文件时并没有把它占用扇区里的数据清零),所以相对就快很多。

4、其实建立或打开文件后想改变文件大小很简单,为什么前面有的朋友的做法是移动文件指针到某一位置后写入一点数据也很快呢。其实这些写入时调用了SDK的另一个关健函数:SetEndOfFile。

5、最快的解决方案:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE BigFile;
DWORD Begin, End;

Begin = GetTickCount();
BigFile = CreateFile("BigFile.bin", // 文件名
GENERIC_READ | GENERIC_WRITE, // 读、写操作
FILE_SHARE_READ | FILE_SHARE_WRITE, // 读、写共享
NULL, // 安全描述符:缺省
OPEN_ALWAYS, // 总是打开,没有则建立
FILE_ATTRIBUTE_NORMAL, // 文件属性:常规
NULL // 临时文件句柄:无
);
if(BigFile != INVALID_HANDLE_VALUE) // 打开或建立成功
{
if(SetFilePointer(BigFile, 800*1024*1024, NULL, FILE_BEGIN) != 0xFFFFFFFF)
{//文件指针移动成功
if(SetEndOfFile(BigFile)) // 设置文件结束符,这才是问题的本原。:):):)
{
End = GetTickCount();
Memo1->Lines->Add(End-Begin); // BCB6SP4/WIN2KSP4/PIII600/128M/4500RPM硬盘笔计本电脑: 80毫秒,YES!
}
}

CloseHandle(BigFile); //使用后关闭句柄
}
}
//---------------------------------------------------------------------------

以此纪念本人下岗9个月。:(
不知道这个解决方案可不可以“入精”。:)
BCB论坛里越来越少人气了。:(
mango279 2006-09-21
  • 打赏
  • 举报
回复
800M的文件,不写进内容,意味着里面的内容都是0。
但是无论用什么办法生成这个文件,系统都要保证再读出来的时候数据是0,因此系统的文件管理要在生成这个文件的时候在磁盘中写800M的0。
这和用什么函数没有关系。
cczlp 2006-09-16
  • 打赏
  • 举报
回复
我用的是
CreateFile然后
SetFilePointer
YJS050320001 2006-09-16
  • 打赏
  • 举报
回复
呵呵
iwenlove 2006-09-15
  • 打赏
  • 举报
回复
用setfilepoint()吧。你查下API函数,把文件的末尾标志移出去就可以了。呵呵。
柯本 2006-09-15
  • 打赏
  • 举报
回复
用低层的I/O试试:
#include <fcntl.h>
#include <io.h>
#include <sys\stat.h>
...
int handle;
handle = open("e:\\temp\\test.bin", O_CREAT|O_RDWR ,S_IREAD|S_IWRITE );
if (handle==NULL)
{
ShowMessage("error");
return;
}
chsize(handle, 1024*1024*800); //改文件大小
close(handle);
老之 2006-09-15
  • 打赏
  • 举报
回复
使用文件流创建文件,将指针移到末端,随便写入一个字节就可以了。

var a:TFileStream;
Buf:PChar;
begin
a := TFileStream.Create('d:\1.tmp',fmCreate);
a.Seek(1024*1024*1024,soFromEnd);
a.Write(Buf,1);
a.Free;
end;
LuoGD 2006-09-15
  • 打赏
  • 举报
回复
应该是对文件分配表操作!不太清楚,网上查找相关资料
jiangshx 2006-09-15
  • 打赏
  • 举报
回复
楼上诸位不是人,是神!

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧