fwrite()会让你写出超出文件大小结尾的东西吗?

时间:2018-01-27 06:01:50

标签: c gcc

FILE *f = fopen("file.txt", "ab+");
fseek(f, NUMBER_BIGGER_THAN_FILE_SIZE, SEEK_SET);
fwrite(&someStruct, sizeof someStruct, 1l, f);

所以,如果我有类似的东西,是否会允许这样写?如果没有,我怎么能做到这一点?

2 个答案:

答案 0 :(得分:1)

可以在文件末尾写入。

但是,在a模式下(追加模式)fseekfwrite无效。

这在C标准7.19.5.3 fopen:

中有记载
  

打开带有追加模式的文件('a'作为mode参数中的第一个字符)会导致对文件的所有后续写入强制转换为当前的文件结束,无论是否对fseek函数进行干预调用

来源:https://stackoverflow.com/a/5532426/2005038

答案 1 :(得分:1)

是的,您可以fwrite超过文件末尾(大多数file systems)。如果不能,则fwrite失败(并给出否定结果)。

当然,这需要先前的fseek调用成功并更改写入的文件偏移量。你需要检查一下。由于d3L answeredfseek可能只会更改fwrite不会用于追加文件的偏移量。

您可能希望fopen使用其他模式。不要使用a追加模式。

例如,您可能在下面有文件tryappend.c(它有大约509个字节):

// file tryappend.c, copy it to tryappend.c2 before running
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    const char* filnam = "tryappend.c2";
    FILE *f = fopen(filnam, "a+");
    if (!f) 
       { perror(filnam); exit(EXIT_FAILURE); };
    if (fseek(f, 1024, SEEK_SET)<0) 
       { perror("fseek"); exit(EXIT_FAILURE); };
    const char str[] = "//// ADDED STUFF\n";
    if (fwrite(str, sizeof(str), 1L, f)<0) 
       { perror ("fwrite"); exit(EXIT_FAILURE); }
    fclose(f);
    printf("changed %s\n", filnam);
    return 0;
}

并在运行tryappend.c2可执行文件之前将其复制到tryappend。然后你可以用二进制编辑器或用例如od在Linux上,fwrite - n的东西已经附加在偏移量510(而不是1024),最后你的tryappend.c2文件只有527个字节(不像1040)。

如果您坚持使用直接访问的文件,则可以使用较低级system calls,例如(在Linux或POSIX上)open(2)read(2)write(2),{ {3}},lseek(2)ftruncate(2)mmap(2)等...请注意,出于性能原因,您应经常使用大缓冲区(read或{{1至少几千字节的块)。顺便说一句,在Linux上,C标准库(所以write例程,包括<stdio.h>freadclose(2),......)正在使用此类系统调用。

您可能拥有不可搜索的文件。一个很好的例子是Linux上的fwrite文件系统中的一些伪文件(参见fflush),例如/procproc(5) - ed文件。

您可以查找库,为您提供比直接访问文件更高级别的抽象,例如popen(3)sqlite(我建议使用这些)。当然,你可以使用一些gdbm。另请阅读database

您应该逐字节地定义和 文档,正好是您的sparse files (可能使用一些file format表示法)。您可能应该关心文件格式的EBNF(考虑portabilityendianness,字大小等问题),或者提供一种方法来将二进制文件填充或转储到更多文件中便携式文本格式。