fread 仅 .PNG 文件的前 5 个字节
我制作了一个简单的资源打包程序,用于将我的游戏资源打包到一个文件中。一切都很顺利,直到我开始编写解包程序。 我注意到我打包的 .txt 文件 - 26 字节 - 从资源文件中正常出来,没有任何问题,所有数据都保留了。 然而,当读取我打包在资源文件中的 .PNG 文件时,前 5 个字节完好无损,而其余字节则完全无效。
我将其追溯到打包过程,我注意到 fread 仅读取 .PNG 文件的前 5 个字节,而我一生都无法弄清楚原因。它甚至触发“EOF”,表明该文件只有 5 个字节长,而实际上它是一个 787 字节的 PNG 小多边形,100 像素 x 100 像素。
我什至通过创建一个单独的应用程序来简单地将这个 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;
}
有人可以指出我的愚蠢错误吗?
I've made a simple resource packer for packing the resources for my game into one file. Everything was going fine until I began writing the unpacker.
I noticed the .txt file - 26 bytes - that I had packed, came out of the resource file fine, without anyway issues, all data preserved.
However when reading the .PNG file I had packed in the resource file, the first 5 bytes were intact while the rest was completely nullified.
I traced this down to the packing process, and I noticed that fread is only reading the first 5 bytes of the .PNG file and I can't for the life of me figure out why. It even triggers 'EOF' indicating that the file is only 5 bytes long, when in fact it is a 787 byte PNG of a small polygon, 100px by 100px.
I even tested this problem by making a separate application to simply read this PNG file into a buffer, I get the same results and only 5-bytes are read.
Here is the code of that small separate application:
#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;
}
Can somebody please point out my stupid mistake?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Windows平台,我猜?
使用此:
而不是此:
请参阅 msdn 了解解释。
Windows platform, I guess?
Use this:
instead of this:
See msdn for explanation.
扩展来自 SigTerm 的正确答案,此处下面是为什么在文本模式下打开 PNG 文件时获得的效果的一些背景信息:
PNG 格式解释了它的 8字节文件头如下:
我相信在文本模式下,对
fread()
的调用在读取包含 Ctrl+Z 字符的第六个字节时终止。 Ctrl+Z 历史上曾在 MSDOS(以及之前的 CPM 中)用于指示文件结束,这是必要的,因为文件系统将文件大小存储为块计数,而不是字节计数。通过以文本模式而不是二进制模式读取文件,您触发了防止意外使用
TYPE
命令显示 PNG 文件的保护。您可以做的有助于诊断此错误的一件事是稍微不同地使用
fread()
。您没有测试fread()
的返回值。你应该。此外,您应该这样调用它:以便 nread 是实际写入缓冲区的字节数。对于文本模式下的 PNG 文件,它会在第一次读取时告诉您它只读取了 5 个字节。由于文件不可能那么小,因此您会知道发生了其他事情。缓冲区的剩余字节从未被
fread()
修改,如果您将缓冲区初始化为其他填充值,就会看到这种情况。Extending the correct answer from SigTerm, here is some background of why you got the effect you did for opening a PNG file in text mode:
The PNG format explains its 8-byte file header as follows:
I believe that in text mode, the call to
fread()
was terminated when it read the sixth byte which contains a Ctrl+Z character. Ctrl+Z was historically used in MSDOS (and in CPM before it) to indicate the end of a file, which was necessary because the file system stored the size of a file as a count of blocks, not a count of bytes.By reading the file in text mode instead of binary mode, you triggered the protection against accidentally using the
TYPE
command to display a PNG file.One thing you could do that would have helped diagnose this error is to use
fread()
slightly differently. You didn't test the return value fromfread()
. You should. Further, you should call it like this:so that
nread
is a count of the bytes actually written to the buffer. For the PNG file in text mode, it would have told you on the first read that it only read 5 bytes. Since the file cannot be that small, you would have had a clue that something else was going on. The remaining bytes of the buffer were never modified byfread()
, which would have been seen if you initialized the buffer to some other fill value.