You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于printf处理二进制文件字符串的两类技术疑问

关于二进制文件读取与打印的常见问题解析

先看这段将文件读取到内存的代码:

FILE *fileptr; char *buffer; long filelen; 
fileptr = fopen("myfile.txt", "rb"); // 以二进制模式打开文件
fseek(fileptr, 0, SEEK_END); // 跳转至文件末尾
filelen = ftell(fileptr); // 获取当前文件字节偏移量
rewind(fileptr); // 跳转回文件开头
buffer = (char *)malloc((filelen+1)*sizeof(char)); // 分配足够存文件内容+终止符的内存
fread(buffer, filelen, 1, fileptr); // 读取整个文件内容
fclose(fileptr); // 关闭文件

这段代码能把文件内容读取成字节数组,本质可以当作字符串使用。如果再添加以下两行代码:

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]); 
} 

结果运行后屏幕输出全是乱码,哪怕把字符串类型改成unsigned char,结果还是一样。

下面来解答这两个核心疑问:

疑问1:为何printf在处理二进制文件时不将buffer视为字符串?

这得从printf("%s")的工作逻辑说起:它会从传入的指针位置开始逐个输出字符,直到碰到**\0(空字符,ASCII码为0)**才会停止。但二进制文件里经常会包含ASCII码为0的字节——比如可执行文件、图片文件中,这类字节是文件结构的必要组成部分,并非字符串终止符。所以printf("%s")读到第一个\0就直接停止输出,根本无法打印完整的二进制文件内容。

而文本文件里的内容都是可打印字符(或换行、制表这类常见控制字符),不会随意出现\0,所以用%s格式打印完全没问题。

疑问2:为何traverse函数中的printf输出乱码而非正常字符?

二进制文件里的字节可不都是可打印字符!比如图片的像素数据、可执行文件的机器指令,很多字节对应的ASCII码属于非打印控制字符(比如ASCII码0-31、127),这些字符输出到终端时,要么显示成乱码、方块,要么会触发终端的特殊行为(比如响铃、光标跳转)。

哪怕把char改成unsigned char,也只是改变了字节的符号解读方式(不会把负数当作符号位),但这些字节对应的字符本身就是不可打印的,终端无法将它们转换成人类能看懂的正常字符,自然就显示成乱码了。


内容的提问来源于stack exchange,提问作者anjanik012

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:07:18