Windows上的read()系统调用无法读取二进制文件

时间:2011-08-24 22:13:14

标签: c windows

我想在使用SDL之前读取图像文件以将它们保存在内存中。我刚刚意识到Windows上的open()和read()无法完全读取我的文件,但是在Linux / BSD上它可以工作!

这是我的代码:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#define IMGPATH "rabbit.png"

int
main(int argc, char *argv[])
{
    int fd;
    struct stat st;
    void *data;
    size_t nbread;

    fd = open(IMGPATH, O_RDONLY);
    if (fd < 0)
        exit(1);

    fstat(fd, &st);

    data = malloc(st.st_size);
    if (data == NULL)
        exit(1);

    nbread = read(fd, data, st.st_size);
    if (nbread != st.st_size)
        printf("Failed to read completely: expected = %ld, read = %ld\n", st.st_size, nbread);
}

在Windows上它将产生:无法完全读取:expected = 19281,read = 5. perror()表示没有错误,如果我再次尝试读取()它不会改变并停留在这5个字节。

是否有一些标志我应该添加到open()来读取二进制文件?

这是我尝试阅读的第一个PNG字节文件:

0000000 211   P   N   G  \r  \n 032  \n  \0  \0  \0  \r   I   H   D   R
0000010  \0  \0  \0   \  \0  \0  \0   k  \b 006  \0  \0  \0   <FA> 220   <E5>

当'\ n'出现时,是否会停止阅读?

我现在不知道如何解决这个问题。

PS:请不要说“使用libpng”,因为在将它与SDL和我的图形库一起使用之前,我只需要将文件缓冲区放入内存中。

1 个答案:

答案 0 :(得分:5)

几点:

  1. read()无法保证读取指定的字节数。它可能提前返回或根本不返回。必须多次调用read()来填充大缓冲区是正常的。这是stdio包装器和fread()有用的原因之一。

  2. 在Windows上,文本和二进制模式不同。由于您未在标志中指定O_BINARY,因此Windows将以不同方式处理此文件的'\n'个字符。可能它会在遇到的第一个'\n'时返回。

  3. 在读取文件之前无需检查文件大小。 read()以及read()周围的任何包装将始终在文件末尾停止读取。

  4. Update0

    进一步观察我发现第5和第6个字符是\r\n,这是在文本模式下由Windows专门处理的,并解释了我在上面提到的早期返回。如果您未将O_BINARY传递给open()来电,则这2个字符将转换为单个\n