read() syscall on windows fails to read binary file

≯℡__Kan透↙ 提交于 2021-02-10 06:16:07

问题


I would like to read image file to keep them in memory before using them with SDL. I just realized that open() and read() on windows fails to read my file entirely but on linux/BSD it works!

This is my code:

#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);
}

On windows it will produce: Failed to read completely: expected = 19281, read = 5. perror() says no error and if I try to read() again it does not change and stuck at this 5 byte.

Is there some flag I should add to open() to read binary file?

This is the first PNG bytes file I try to read:

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>

Does it stops reading when '\n' appears?

I don't know how to fix this right now.

PS: please do not says "use libpng" because I just need to get the file buffer into memory before using it with SDL and my graphic library.


回答1:


A few points:

  1. read() is not guaranteed to read the count of bytes specified. It may return early or nothing at all. It's normal to have to call read() several times to fill large buffers. This is one of the reasons the stdio wrappers and fread() are useful.

  2. On Windows, text and binary mode differ. Since you did not specifiy O_BINARY in your flags, Windows will handle '\n' characters differently for this file. Likely it is returning at the first '\n' encountered.

  3. It's not necessary to check the file size before reading the file. The read() and indeed any wrapper around read() will always stop reading at the end of the file.

Update0

On further observation I see that the 5th and 6th characters are \r\n, this is handled specially by Windows when in text mode, and explains the early return as I mentioned above. If you don't pass O_BINARY to the open() call these 2 characters will be converted to a single \n.



来源:https://stackoverflow.com/questions/7182957/read-syscall-on-windows-fails-to-read-binary-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!