我已经制作了一个简单的资源包装器,用于将我的游戏资源打包到一个文件中。在我开始编写解包器之前,一切都很顺利。 我注意到我已经打包的.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;
}
有人可以指出我的愚蠢错误吗?
答案 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}}修改,如果您将缓冲区初始化为其他填充值,则会看到这些字节。