代码之家  ›  专栏  ›  技术社区  ›  Sam Blackburn

仅读取.PNG文件的前5个字节

  •  9
  • Sam Blackburn  · 技术社区  · 14 年前

    我做了一个简单的资源打包器,把游戏的资源打包成一个文件。一切都很顺利,直到我开始写解包。 我注意到我打包的.txt文件(26字节)很好地从资源文件中出来,没有任何问题,所有数据都保留了下来。 但是,当读取我在资源文件中打包的.PNG文件时,前5个字节是完整的,而其余的则完全为空。

    我把它追溯到打包过程,我注意到fread只读取.PNG文件的前5个字节,我一辈子都搞不懂为什么。它甚至会触发“EOF”,表示文件只有5个字节长,而实际上它是一个787字节的小多边形PNG,100px x x 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 回复  |  直到 14 年前
        1
  •  21
  •   SigTerm    14 年前

    我想是Windows平台吧?

    使用此选项:

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

    而不是这样:

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

    看到了吗 msdn 请解释一下。

        2
  •  8
  •   Community paulsm4    7 年前

    扩展 correct answer from SigTerm ,以下是 为什么? 在文本模式下打开PNG文件的效果如下:

    8-byte file header 具体如下:

       (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的坏文件传输。第二到第四个字节命名格式。CR-LF序列捕获改变换行序列的错误文件传输。control-Z字符在MS-DOS下停止文件显示。最后的换行检查CR-LF转换问题的逆问题。

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

    TYPE 显示PNG文件的命令。

    您可以做一件有助于诊断此错误的事情,那就是使用 弗雷德() 稍有不同。您没有测试来自的返回值 . 你应该。此外,您应该这样称呼它:

    ...
    size_t nread;
    ...
    nread = fread(buffer, sizeof(buffer), 1, f);
    

    以便 nread 实际写入缓冲区的字节数。对于文本模式下的PNG文件,它在第一次读取时会告诉您它只读取5个字节。既然文件不能那么小,你就有了其他事情的线索。缓冲区的剩余字节从未被修改 弗雷德()