行进中开火

C++夜未眠

快速扩展文件大小

首先转一段博文:Linux下快速扩展文件大小

 在实际的开发过程中,我们可能需要在文件生成时就立即将文件更改为指定的大小,以便于后续简化对文件的并发操作,
这一点在各类的下载工具中有很好的体现。
    要满足这一需求,通常可以使用的最直观的方式是:生成文件后,通过循环向文件中写入任意数据,直到文件大小达到预期的大小。
对于较小的文件,这种方法可以接受,但是如果文件大小过大,那么这种方法就显得不够简洁且低效。
    这里介绍一种高效且简单的方法,基于函数"lseek"。
    执行"man lseek"之后,我们可以看到关于lseek特性的关键信息,如下:
    The lseek() function shall allow the file offset to be set beyond the end of the existing data in the file. 
    If data is later written at this point, subsequent reads of data in the gap shall return bytes with the 
    value 0 until data is actually written into the gap.
    The lseek() function shall not, by itself, extend the size of a file.

简单的总结就是:
1. lseek 函数本身不会扩展文件的大小.
2. lseek 允许文件的偏移值超过文件的末端,如果下一次在这个偏移点写入数据,那么在偏移之前的文件末端与偏移点之间的数据将会自动填充为0。

了解了上面几点,大家应该想到了扩展文件大小将是一件多么简洁高效的事情了:)  

那么,简单的步骤如下


1. lseek( iFileHandle , 0 , SEEK_CUR ); //保存文件指针的当前位置以便于在扩展文件大小后恢复到当前位置 2. lseek( iFileHandle , iMoveOffset , SEEK_SET ); 3. write( iFileHandle , " " , WRITE_BYTE_COUNT ); //写入一个字节的数据,完成对文件大小的更改 4. lseek( iFileHandle , iCurPos , SEEK_SET ); //恢复文件指针到之前保存的文件位置

实际上,在Windows中的_lseek或者_lseeki64也可以达到相同的目的。MSDN中的描述:

You can use _lseek to reposition the pointer anywhere in a file or beyond the end of the file.


最后,还有一个更好的方法:

int truncate(const char *path, off_t length); 
If the file previously was larger than length, the extra data is discarded. 
If the file was previously shorter than length, its size is increased, and the extended area appears as if it were zero-filled. 
这样一来,截断和扩展文件都可以用"truncate"来完成,这样相对于上面的EnlargeFile就更简洁了而且基于"truncate"的形式只需要一次系统调用即可实现相同的效果,效率上也更有优势. 

但是,truncate函数在Windows中不可以使用。可以使用 SetEndOfFile 来代替。

 

Truncating or Extending Files

An application can truncate or extend a file by calling SetEndOfFile on sets the end-of-file marker to the current position of the file pointer.

Note that when a file is extended, the contents between the old and new end-of-file locations are not defined.

 

The SetEndOfFile function can be used to truncate or extend a file. If the file is extended, the contents of the file between the old end of the file and the new end of the file are not defined.

SetEndOfFile 可以用来扩展文件,当一个文件被扩展,被扩展部分,是未被定义的。也就是说,新扩展出来的部分,没有被付初值,没有用0填充。

还需要注意一点,

If CreateFileMapping is called to create a file mapping object for hFileUnmapViewOfFile must be called first to unmap all views and call CloseHandle to close the file mapping object before you can call SetEndOfFile.

也就是说,在Mapping状态的文件,是不能调用SetEndOfFile的。

MSDN链接:http://msdn.microsoft.com/en-us/library/aa365531(VS.85).aspx

 

 

 

 

posted on 2010-03-03 17:57 Jakcie 阅读(813) 评论(0)  编辑 收藏 引用 所属分类: C++ & CLinux & QT


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理