fread只有.PNG文件的前5个字节

时间:2010-08-22 19:45:59

标签: c file-io stdio msvcrt fread

我已经制作了一个简单的资源包装器,用于将我的游戏资源打包到一个文件中。在我开始编写解包器之前,一切都很顺利。 我注意到我已经打包的.txt文件--26个字节 - 来自资源文件,没有任何问题,保留了所有数据。 但是,当我读取我在资源文件中打包的.PNG文件时,前5个字节是完整的,而其余的则完全无效。

我追溯到打包过程,我注意到fread只读取.PNG文件的前5个字节,我不能为我的生活找出原因。它甚至触发'EOF'表示文件只有5个字节长,实际上它是一个787字节的小多边形PNG,100px×100px。

我甚至通过单独的应用程序将这个PNG文件读入缓冲区来测试这个问题,我得到相同的结果,只读取5个字节。

以下是该小型独立应用程序的代码:

#include <cstdio>

int main(int argc, char** argv)
{
    char buffer[1024] = { 0 };
    FILE* f = fopen("test.png", "r");
    fread(buffer, 1, sizeof(buffer), f);
    fclose(f);        //<- I use a breakpoint here to verify the buffer contents
    return 0;
}

有人可以指出我的愚蠢错误吗?

2 个答案:

答案 0 :(得分:21)

  

有人可以指出我的愚蠢错误吗?

Windows平台,我想?

使用此:

FILE* f = fopen("test.png", "rb");

而不是:

FILE* f = fopen("test.png", "r");

请参阅msdn了解相关信息。

答案 1 :(得分:8)

扩展correct answer from SigTerm,以下是为什么您在文本模式下打开PNG文件时所起作用的背景:

PNG格式解释其8-byte file header如下:

  

PNG文件的前八个字节始终包含以下值:

   (decimal)              137  80  78  71  13  10  26  10
   (hexadecimal)           89  50  4e  47  0d  0a  1a  0a
   (ASCII C notation)    \211   P   N   G  \r  \n \032 \n
  

此签名既将文件标识为PNG文件,又可立即检测常见的文件传输问题。前两个字节区分系统上的PNG文件,这些文件期望前两个字节唯一地标识文件类型。选择第一个字节作为非ASCII值,以降低文本文件被误识别为PNG文件的可能性;此外,它捕获了清除第7位的错误文件传输。字节2到4命名格式。 CR-LF序列捕获改变换行序列的错误文件传输。 control-Z字符在MS-DOS下停止文件显示。最后换行符检查CR-LF转换问题的反转。

我相信在文本模式下,当fread()读取包含Ctrl + Z字符的第六个字节时,对TYPE的调用终止。 Ctrl + Z历史上用于MSDOS(以及之前的CPM)以指示文件的结尾,这是必要的,因为文件系统将文件大小存储为块的计数,而不是字节数。

通过以文本模式而不是二进制模式读取文件,您触发了防止意外使用fread()命令显示PNG文件的保护。

你可以做的有助于诊断此错误的一件事是使用fread()略有不同。您没有测试... size_t nread; ... nread = fread(buffer, sizeof(buffer), 1, f); 的返回值。你应该。此外,您应该这样称呼它:

nread

以便fread()是实际写入缓冲区的字节数。对于文本模式下的PNG文件,它会在第一次读取时告诉您它只读取5个字节。由于文件不能那么小,你可能已经知道其他事情正在发生。缓冲区的剩余字节从未被{{1}}修改,如果您将缓冲区初始化为其他填充值,则会看到这些字节。