我有这段 C 代码:
[...]
struct stat info;
char *filename = "just_a_binary_file";
stat(filename, &info);
printf("FILE SIZE: %d\n", info.st_size);
char *content = (char *)malloc(info.st_size * sizeof(char *));
FILE *fp = fopen(filename, "rb");
fread(content, info.st_size, 1, fp);
fclose(fp);
printf("STRING LENGTH: %d\n", strlen(content));
[...]
输出是:
FILE SIZE: 20481
STRING LENGTH: 6
问题是文件包含一些零字节,当我将文件内容放入变量char *时,字符串在第一次出现'\ 0'时被截断(恰好是chr(0))。
问题是如何将完整的二进制内容转换为变量char *?
答案 0 :(得分:2)
首先,你分配了太多的内存。 info.st_size * sizeof(char)
就够了。你存储字符,而不是指针。
然后您需要存储文件大小并使用内存函数而不是字符串函数。包含空字节的数据块不是每个定义的字符串。因此除了使用已知的文件大小之外,不可能获得它的长度。
答案 1 :(得分:1)
在我看来,您确实已将完整的二进制文件读入content
。二进制数据不是字符串数据。字符串以NULL结尾。当您检查调试器中的内容时,是的,它看起来被截断,但实际上,它的大小为20481字节。查看内存中的content
,您应该看到所有内容。
答案 2 :(得分:1)
您已成功加载整个文件。
但它包含零,而零表示(:))零终止字符串的结尾。 strlen()
对你没有任何好处。
答案 3 :(得分:1)
你正在做什么似乎没问题,问题在于strlen ......当它遇到'\ 0'时会停止计数。 fread
会将其撰写的元素数量返回给content
。
答案 4 :(得分:1)
以下是您的代码的修改版本。与你的比较。
struct stat info;
const char *filename = "just_a_binary_file";
if (stat(filename, &info) != 0) {
/* error handling */
}
printf("FILE SIZE: %lu\n", (unsigned long)info.st_size);
char *content = malloc(info.st_size);
if (content == NULL) {
/* error handling */
}
FILE *fp = fopen(filename, "rb");
if (fp == NULL) {
/* error handling */
}
/* Try to read a single block of info.st_size bytes */
size_t blocks_read = fread(content, info.st_size, 1, fp);
if (blocks_read != 1) {
/* error handling */
}
fclose(fp);
/*
* If nothing went wrong, content now contains the
* data read from the file.
*/
printf("DATA LENGTH: %lu\n", (unsigned long)info.st_size);
请注意,在某些情况下,此方法仍然容易出错。例如,stat()
会在您调用stat()
时为您提供文件的大小。在调用stat()
和实际读取文件之间,文件的大小可能已经改变。