C 来自fread()的意外返回值

C 来自fread()的意外返回值,c,fread,bmp,C,Fread,Bmp,偏移量输出似乎正确,因为文件大小为698454字节(=698400+54)。但是,fread()返回的值似乎表明无法读取整个图像数据。但是,我随后使用temp数组中的数据将RGB数据转换为灰度,并再次将该数据写入BMP文件。目测检查输出图像并不表示有任何错误,也就是说,尽管fread()的指示似乎有所不同,但我似乎一开始就读取了整个输入图像 有人能解释一下这种行为吗?(我敢打赌你在Windows上) 应该是 bmp = fopen("test_colour.bmp", "r"); 如果文件是在

偏移量输出似乎正确,因为文件大小为698454字节(=698400+54)。但是,
fread()
返回的值似乎表明无法读取整个图像数据。但是,我随后使用
temp
数组中的数据将RGB数据转换为灰度,并再次将该数据写入BMP文件。目测检查输出图像并不表示有任何错误,也就是说,尽管
fread()
的指示似乎有所不同,但我似乎一开始就读取了整个输入图像

有人能解释一下这种行为吗?

(我敢打赌你在Windows上)

应该是

bmp = fopen("test_colour.bmp", "r");
如果文件是在Windows上以文本模式打开的,则运行时将在遇到0x1a(Ctrl-Z)字节时停止读取,Windows将该字节视为文本文件的EOF标记。即使它没有按Ctrl-Z键,当Windows将CR/LF序列转换为单个LF字符时,也会得到损坏的数据

但是,我无法解释为什么您能够从部分文件读取中获得良好的图像(只是幸运吗?)

您可以从缓冲区渲染图像,因为
fread()
实现确实将您请求的字节数(或几乎如此-该数字向下舍入到某个块大小的倍数)读取到缓冲区,然后它扫描缓冲区,查找要转换的CR/LF序列和Ctrl-Z EOF标志

因此,即使
fread()
返回
33018
,缓冲区实际上已经几乎完全用文件中的数据写入。数据不是100%正确(例如,某些CR字符可能已被丢弃)或完整,但在本例中,数据足够接近,可以渲染出与预期图像相似的图像


当然,这只是对当前这个特定运行时行为的观察-它在将来可能不会总是这样(甚至在今天的所有系统上)。

两个问题:1)在调用
fread
后,您能否检查
temp
的内容,以查看它是否在33018字节后实际停止读取?2) 我不熟悉
%Iu
格式说明符-您能在调试器中检查
read
的实际值吗?我认为这不是导致您看到症状的原因,但您应该使用正确的
printf
格式字符串。
size\u t
的格式为
“%zu”
<代码>“%Iu”是非标准的。如果您的实现不支持
“%zu”
,则可以使用
printf(“%lu字节读取!\n”,(无符号长)读取)
我正在使用gcc和MinGW进行编译,但编译器无法识别
%zu
说明符(我以前尝试过使用该说明符)。我读到人们必须在windows中使用
%Iu
。@simon:有关为什么MinGW在支持的
printf()
格式说明符上会有点混乱的信息,请参阅。较新的MinGW版本和/或MSVCRT.DLL的较新版本似乎支持越来越多的C99标准说明符。“但是,我随后使用临时数组中的数据将RGB数据转换为灰度,并将此数据再次写入BMP文件”。你能测试新bmp文件的大小吗?它是否大于33 KB?nem文件的尺寸是600*388像素吗?事实上,我忘了在OP中提及。感谢您指出这一点,解决了问题!你确定它真的停止阅读了吗?如前所述,我仍然能够给出整个BMP图像的正确灰度图像,尽管根据
fread
只有~5%的文件数据被实际读取。@simon:运行时可能会将您请求的字节数读入缓冲区,然后检查并“修复”行结尾和EOF翻译。但我只是猜测。我将生成的两个输出图像(一个是用
“r”
打开文件,另一个是用
“rb”
打开文件)与diff进行了比较,结果发现它们不一样。从视觉上看,唯一的区别似乎是
“r”
图像中的最后几个像素是黑色的,而实际上它们应该是白色的。因此,我猜
fread
实际上读取的字节数比返回值指示的字节数多,但不一定是请求的实际字节数。在“r”模式下,某些字节由于其值而无法读取。因此,在“r”模式下读取的字节数比在“rb”模式下读取的字节数少是正常的“r”模式仅用于读取文本文件。
Offset = 54
698400 bytes requested!
33018 bytes read!
bmp = fopen("test_colour.bmp", "r");
bmp = fopen("test_colour.bmp", "rb");