来自这篇文章https://stackoverflow.com/a/22059317/5859944
FILE *fileptr;
char *buffer;
long filelen;
fileptr = fopen("myfile.txt", "rb"); // Open the file in binary mode
fseek(fileptr, 0, SEEK_END); // Jump to the end of the file
filelen = ftell(fileptr); // Get the current byte offset
in the file
rewind(fileptr); // Jump back to the beginning of
the file
buffer = (char *)malloc((filelen+1)*sizeof(char)); // Enough memory
for file + \0
fread(buffer, filelen, 1, fileptr); // Read in the entire file
fclose(fileptr); // Close the file
您将文件读取为字节数组。
很明显它只不过是一根绳子。 可以添加一个
buffer[filelen] = '\0';
和
printf("%s" , buffer);
应该打印文件的委托内容,就好像它是一个字符串一样。它在简单的文本文件中完成,但不在二进制文件中。
对于二进制文件,必须按如下方式编写函数:
void traverse(char *string ,size_t size){
for(size_t i=0;i<size;i++)
printf("%c",string[i]);
}
逐个打印每个字符。 这会在屏幕上显示乱码。
printf
不会将buffer
视为包含二进制文件的字符串?printf
中的traverse
会出现乱码而不是字符?对于第二个要点,我知道这可能是由于signed char
,但即使字符串存储为unsigned char
,结果仍然相同。
答案 0 :(得分:2)
为什么printf不会将缓冲区视为包含二进制文件的字符串?
printf("%s",buffer)
确实假设buffer
包含C字符串。问题是,这不是buffer
实际包含的内容。您的buffer
实际上包含二进制文件中的字节。
C字符串由第一个零字节(a.k.a。,'\ 0',a.k.a。,ASCII NUL)终止,并且任意非文本文件(a.k.a。,“二进制文件”)可以在其自身内的任何位置包含零字节。 printf“%s”格式一看到第一个零字节就会停止。
为什么函数遍历中的printf会出现乱码而不是字符?
“乱码”是字符。但是这些字符并不意味着任何东西,因为你试图解释为一系列字符的文件并不意味着以这种方式解释。
文本文件是一系列字节,意在根据某些 character encoding 呈现,而通常意味着传达某种人类可读的信息。任意“二进制”文件可能包含不应该表示人类可读文本的字节序列。它们代表了其他一些计算机程序能够理解的东西。
printf "%s"
尝试根据某些字符编码系统(通常是UTF-8或US-ASCII)渲染这些字节,但是(a)它赢了总是能够这样做,(b)即使 能够这样做,字符序列也不会有任何意义。
答案 1 :(得分:1)
这里的第一个问题是你正在混淆阅读文件的目的。要从文件中读取二进制数据,然后打印该二进制数据,您应始终使用unsigned char
和unsigned char*
来存储从二进制文件中读取的数据文件。
这是因为为了准确表示打印的数据,您需要在"%u"
格式字符串中使用printf
类型标记。根据ASCII,只有some characters are printable,这意味着如果您希望查看文件中的所有二进制数据,则在使用"%c"
标志时,您将无法看到其中的一些数据。
你的函数的二进制版本是:
void traverse(unsigned char *string ,size_t size){
for(size_t i=0;i<size;i++)
printf("%u",string[i]);
}
第二个问题是
应该打印文件的委托内容,就好像它是一个字符串一样。它在简单的文本文件中完成,但不在二进制文件中。
事实并非如此。使用"%s"
标志打印字符就好像它们是可打印的字符一样,它会在到达空\0
字符时终止。您无法有效地使用%s
打印二进制数据。