【问题标题】:Will fwrite() let you write something past the end of the file size?fwrite() 会让你写超出文件大小末尾的东西吗?
【发布时间】:2018-01-27 06:01:49
【问题描述】:
FILE *f = fopen("file.txt", "ab+");
fseek(f, NUMBER_BIGGER_THAN_FILE_SIZE, SEEK_SET);
fwrite(&someStruct, sizeof someStruct, 1l, f);

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

【问题讨论】:

  • 查看fseek的返回值——是否成功?
  • @coderredoc 是的,它成功了。
  • 你为什么要这样做?为什么不使用一些更高级别的抽象(例如sqlite...)
  • @BasileStarynkevitch 学习

标签: c gcc


【解决方案1】:

可以覆盖文件末尾。

但是在a 模式下(附加模式)fseekfwrite 没有影响。

这在 C 标准 7.19.5.3 fopen 中有记录:

使用附加模式(“a”作为模式参数中的第一个字符)打开文件会导致所有后续对该文件的写入都被强制到当前的文件结尾,而不管对 fseek 函数的干预调用.

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

【讨论】:

  • 你确定吗?在 Linux 上可能不是这样。
  • 那么我怎样才能打开文件来读写二进制文件而不删除它的内容呢?
  • @BasileStarynkevitch 是的,请参阅stackoverflow.com/a/5532426/2005038
  • @MauricioMartinez 使用r+b
  • @d3L:您的答案中应包含该参考资料
【解决方案2】:

是的,您可以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 可执行文件之前将其复制到tryappend.c2。然后你可以用二进制编辑器或例如检查。 od 在 Linux 上 fwrite-n 的内容已附加在偏移量 510(不是 1024)处,最后你的 tryappend.c2 文件只有 527 个字节(不是 1040 之类的东西)。

如果您坚持直接访问文件,您可以使用较低级别的system calls,例如(在 Linux 或 POSIX 上)open(2)read(2)write(2)lseek(2)ftruncate(2)、@ 987654332@、close(2) 等...请注意,出于性能原因,您通常应该使用大缓冲区(因此,readwrite 至少有几千字节的块)。顺便说一句,在 Linux 上,C 标准库(所以&lt;stdio.h&gt; 例程,包括freadfwritefflush,...)正在使用这样的系统调用。

您可能拥有不可搜索的文件。一个很好的例子是在 Linux 上来自/proc 文件系统的一些伪文件(参见proc(5)),例如/proc/self/mapspopen(3)-ed 文件。

您可以找到比直接访问文件具有更高抽象级别的库,例如sqlitegdbm(我建议使用这些)。当然,您可以使用一些database。另请阅读sparse files

您应该逐字节精确地定义并记录您的file format(可能使用一些EBNF 表示法)。您可能应该关心文件格式的portability(想想endiannessdata alignment、字长等问题),或者提供一种将二进制文件填充或转储为更便携的文本格式的方法。

【讨论】:

  • 这个答案在一个问题上抛出了很多几乎可以肯定的坏主意和晦涩难懂的功能,但并没有给出任何需要它们的迹象,也没有真正解决问题是附加模式的问题。它还断言了一个可疑的单独读写偏移模型,这不是附加模式的工作方式。
猜你喜欢
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多