如何在C语言中将整个文件加载到字符串中

13

可能是重复问题:
在C中获取文件内容的最简单方法

我的程序读取跨越许多行的文件。我想将文件内容保存在单个字符串中。

我不知道执行之前文件的行数,但是我已将每行大小固定为MAX_LINE_LEN。

你可以如何做到这一点?


1
这个问题至少已经被问过一百次了,我猜想。 - akappa
2个回答

27

fread()函数不关心换行符。以下代码读取input_file_name的内容,并将其保存到数组file_contents中:

char *file_contents;
long input_file_size;
FILE *input_file = fopen(input_file_name, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc(input_file_size * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);

只有在input_file_name包含\0字符时,您才能从该数组创建字符串。如果没有,请将最后三行更改为:

file_contents = malloc((input_file_size + 1) * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);
file_contents[input_file_size] = 0;

1
将“long long”更改为“size_t”,或者至少使用“long”,这是“ftell”的实际返回类型,然后返回+1。 - Chris Lutz
另外,最后一行不应该是 file_contents[input_file_size + 1] = '\0'; 吗? - Chris
1
@Chris:不是的。大小为2的数组a有元素a[0]a[1]。同样,大小为input_file_size + 1的数组file_contents的最后一个元素是file_contents[input_file_size]。至于0\0,使用字符常量或其整数表示没有区别。 - Dennis
在某些Linux系统文件上使用此方法时,无论其内容如何,输入文件大小(input_file_size)都将返回为1个块。解决方法是使用fread读取的字节数来终止字符串:bytes_read = fread(...); file_contents[bytes_read] = 0; - John
使用fseek/ftell来确定文件大小似乎存在安全问题:https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file - Niklas Peter
显示剩余2条评论

3

1) 使用 fstat 函数确定文件大小。

2) 分配一个长度为文件大小加 1 的零填充缓冲区。

3) 使用 fread 函数将文件内容读入缓冲区。


  1. 在末尾添加一个空终止符。(编辑:好的,我看到你说“清零缓冲区”,但如果你无论如何都要覆盖它,为什么要花费所有时间将每个字节清零呢?虽然在现实生活中并不重要,但仍然存在这个问题。)
- EboMike
公正的观点。虽然我认为与 I/O 开销相比,将缓冲区清零所需的时间微不足道,除非文件非常大。用户可以只清零最后一个字节。 - James
1
如果您使用calloc,在大多数操作系统上它的速度与malloc相同,因为操作系统会在后台执行某些操作以确保内存被清零(以确保calloc(8 * getpagesize())不会花费太长时间),但这当然并不是保证。 - Chris Lutz
@James:完全正确,这就是为什么我说在现实生活中并不重要。我只是太习惯于在一个需要计算每个周期的环境中工作,所以忍不住挑剔一下 :) - EboMike
fstatfopen之间的文件大小会发生变化吗? - joeytwiddle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接