Linux C 读写超过2G的大文件 注意事项
背景
在项目中做大文件的增量读写,遇到了问题:
fopen : Value too large for defined data type.
习惯性地根据这个提示查阅的有关资料显示:
1)工具链太老了:海思的工具链我目前找不到更换的方法,也为了稳定性,不再增加新的ulibc库
2)文件系统的 inde是 64位的:查看了 cat /proc/fs/{文件系统类型}/{设备名}/options
,发现一切正常
显然,这样的结果并不能让我满足。
Linux C/C++ 大文件读写下编程实现的不同
由于上文的方向不对,于是我换了个思路,直接根据需求查找: "Linux C 读写大文件"
了解到了有关信息:
- Linux默认环境下打开、读、写超过2G的文件会返回错误。定义
#define _FILE_OFFSET_BITS 64
宏可以突破这个限制,对read/write和fread/fwrite同时有效。(注意必须定义在<stdio.h>之前。至此,open文件算是没有问题了)
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
细心的读者肯定注意到了,还有2个宏,这2个宏是与 fpos_t 有关的;而这个 fpos_t 与 操作文件偏移量有关。
传统 偏移操作 : fseek()
+ ftell()
fseek(fp,0,SEEK_END);
length = ftell(fp);
fseek( fp, 0, SEEK_SET);
printf("%ld", length );
处理大文件时,ftell 的返回值有问题:要么是-1,要么是_length数据类型的最大值,总之都是不对的。
而正确的方式应该是 使用 : fseek()
+ fgetpos()
或fsetpos()
解决办法是:
fpos_t pos;
fseek(fp,0,SEEK_END);
fgetpos(fp,&pos);
fseek( fp, 0, SEEK_SET);
fseek、ftell() 与 fgetpos()、fsetpos()
我们都知道ftell与fseek一起使用;而fsetpos与fgetpos也要结合fseek使用。
ftell与fseek返回的是长整数,而后面两个则是返回一个新类型:fpos_t
ftell() 用长整型表示文件内的偏移 (位置), 因此, 偏移量被 限制在 20 亿 (231-1) 以内。
而新的 fgetpos() 和 fsetpos() 函数使用 了一个特殊的类型定义 fpos_t 来表示偏移量 (这个类型的值的内容与 _LARGEFILE_SOURCE、_LARGEFILE64_SOURCE 宏有关)
因此, fgetpos() 和 fsetpos 可以表示任意大小的文件偏移,fgetpos() 和 gsetpos() 也可以用来记录多字节流式文件的状态。
基于 mmap 的 大文件读写
我在查阅资料的时候,也发现 可以通过 mmap 的方式来操作大文件(以前读写FrameBuffer的时候就用到了这种方式)
若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
博客地址:https://www.cnblogs.com/schips/