fgetc只读39字节、fread结果异常,如何正确读取文件?
解决WAV文件读取异常:fgetc读取截断与fread异常的问题
问题现象
- 使用
fgetc读取Eva.wav文件时,仅能读取前39字节,后续读取结果全为-1 - 改用
fread后,读取到39字节后出现大量FFxx格式的异常字节码,不清楚两种读取方式结果差异的原因,也不知道正确的文件读取姿势
用户原fgetc代码:
#include <windows.h> #include <stdio.h> int main() { FILE *file =fopen("Eva.wav","r"); if (file==NULL) printf("heresy read!"); for(int i=0;i<200;i++) { char a = fgetc(file); printf("%hhX ",a); } fclose(file); return 0; }
fread改写后的输出(部分):
52 49 46 46 46 FF8C FFA3 0 57 41 56 45 66 6D 74 20 10 0 0 0 1 0 1 0 44 FFAC 0 0 44 FFAC 0 0 1 0 8 0 4C 49 53 54 FF86 FFAA 6A FFFB FFFE 7F 0 0 FF88 2C 40 0 0 0 0 0 0 0 0 0 0 0 0 0 10 15 40 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 1 10 0 0 0 0 60 7 FF96 0 0 0 0 0 FF86 FFAA 6A FFFB FFFE 7F 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FFB0 16 40 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 13 FF96 0 0 0 0 0 FF83 16 40 0 0 0 0 0 1 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 70 13 FF96 0 0 0 0 0 FFB0 16 40 0 0 0 0 0 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FF99 17 40 0 0 0 0 0 10 0 0 0 0 0 0 0 FF99 16 40 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0
问题根源
- 文本模式触发的截断:Windows平台下,
fopen用"r"打开是文本模式,这种模式会把字节0x1A(ASCII的EOF控制字符)当成文件结束标志。你的WAV文件刚好在第39字节左右包含这个字符,所以fgetc读到这里就直接返回EOF(即-1),后续读取全是-1。 - 有符号char的符号扩展:
fgetc返回的是int类型(范围-1到255),你把它存到char里——Windows下默认char是有符号类型,当读取的字节值大于0x7F时,会被转换成负数(比如0x8C变成-116,以补码表示就是0xFF8C),这就是fread输出里大量FFxx的原因,本质是符号扩展导致的显示异常,不是文件分段。
正确的读取方式
核心要点
- 打开二进制文件必须用二进制模式:
fopen("Eva.wav", "rb"),避免文本模式的特殊字符处理 - 用
unsigned char存储读取的字节,防止符号扩展导致的负数显示 - 读取时要正确判断文件结束(
fgetc返回EOF或fread返回的读取数量小于请求数量)
修正后的fgetc版本代码
#include <windows.h> #include <stdio.h> int main() { FILE *file = fopen("Eva.wav", "rb"); if (file == NULL) { printf("heresy read!"); return 1; } int ch; for(int i = 0; i < 200; i++) { ch = fgetc(file); if (ch == EOF) break; printf("%02X ", (unsigned char)ch); } fclose(file); return 0; }
修正后的fread版本代码
#include <windows.h> #include <stdio.h> int main() { FILE *file = fopen("Eva.wav", "rb"); if (file == NULL) { printf("heresy read!"); return 1; } unsigned char buf[200]; size_t read_count = fread(buf, 1, sizeof(buf), file); for(size_t i = 0; i < read_count; i++) { printf("%02X ", buf[i]); } fclose(file); return 0; }
现在两种方式读取的结果会完全一致,都能正确读取WAV文件的二进制内容,不会出现截断或异常字节显示。
内容的提问来源于stack exchange,提问作者phoenixterran
相关产品推荐
相关产品推荐

