fwrite能否写入文件末尾之外?指定代码写法是否可行及实现方法
关于fwrite写入超出文件大小位置的问题
首先直接给结论:是的,fwrite允许写入超出当前文件大小的位置,这种操作会产生所谓的「文件空洞」——也就是文件中逻辑存在但实际未占用磁盘空间的0字节区域(具体是否占用磁盘取决于文件系统是否支持稀疏文件)。
不过你给出的代码并不能实现这个需求,原因出在文件打开模式上:
FILE *f = fopen("file.txt", "ab+"); fseek(f, NUMBER_BIGGER_THAN_FILE_SIZE, SEEK_SET); fwrite(&someStruct, sizeof someStruct, 1l, f);
ab+是追加读写模式,根据C标准的规定,当文件以追加模式(带a标志)打开时,所有写操作都会自动将文件位置指针重置到文件末尾,无论你之前用fseek定位到了哪里。所以你这里的fseek操作会被忽略,写入依然会追加到文件最后,达不到写入指定偏移位置的目的。
正确的实现方式
要实现在超出文件大小的位置写入,你需要使用读写模式但不带追加标志,比如r+b或w+b:
r+b:打开已存在的文件进行读写,不会截断文件;如果文件不存在,fopen会返回NULL。w+b:打开文件进行读写,如果文件不存在则创建,存在则截断为0长度(会丢失原有内容)。
如果需要保留原有文件内容,同时支持写入任意位置(包括超出当前大小),可以先尝试用r+b打开,失败的话再创建文件:
#include <stdio.h> #include <stdlib.h> typedef struct { // 你的结构体定义示例 int id; char name[20]; } SomeStruct; int main() { const long NUMBER_BIGGER_THAN_FILE_SIZE = 1024 * 1024; // 示例偏移量 SomeStruct someStruct = {123, "Test"}; FILE *f = fopen("file.txt", "r+b"); if (f == NULL) { // 文件不存在,创建新文件 f = fopen("file.txt", "w+b"); } if (f == NULL) { perror("Failed to open file"); return EXIT_FAILURE; } // 定位到目标偏移位置 if (fseek(f, NUMBER_BIGGER_THAN_FILE_SIZE, SEEK_SET) != 0) { perror("fseek failed"); fclose(f); return EXIT_FAILURE; } // 写入结构体 size_t written = fwrite(&someStruct, sizeof(SomeStruct), 1, f); if (written != 1) { perror("fwrite failed"); fclose(f); return EXIT_FAILURE; } fclose(f); return EXIT_SUCCESS; }
额外注意事项
- 文件空洞的特性:写入超出当前文件大小的位置后,文件的逻辑大小会变为
NUMBER_BIGGER_THAN_FILE_SIZE + sizeof(someStruct),中间未写入的区域会被视为0字节。在支持稀疏文件的文件系统(如ext4、NTFS)中,这些空洞不会占用实际磁盘空间,直到你往里面写入数据。 - 错误检查:务必检查
fopen、fseek、fwrite的返回值,避免因权限不足、磁盘满等问题导致操作失败却未被发现。
内容的提问来源于stack exchange,提问作者Mauricio Martinez
相关产品推荐
相关产品推荐

