Windows 上的 read() 系统调用无法读取二进制文件 [英] read() syscall on windows fails to read binary file

查看:36
本文介绍了Windows 上的 read() 系统调用无法读取二进制文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的代码:

#include #include #include #include #define IMGPATH "rabbit.png"整数main(int argc, char *argv[]){国际金融;结构统计ST;无效*数据;size_t nbread;fd = 打开(IMGPATH,O_RDONLY);如果 (fd <0)退出(1);fstat(fd, &st);数据 = malloc(st.st_size);如果(数据== NULL)退出(1);nbread = 读取(fd,数据,st.st_size);如果(nbread != st.st_size)printf("无法完全读取:预期 = %ld,读取 = %ld\n", st.st_size, nbread);}

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

我应该在 open() 中添加一些标志来读取二进制文件吗?

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

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

出现'\n'时是否停止读取?

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

PS:请不要说使用 libpng",因为我只需要在将文件缓冲区与 SDL 和我的图形库一起使用之前将其放入内存即可.

解决方案

几点:

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

  2. 在 Windows 上,文本和二进制模式不同.由于您没有在标志中指定 O_BINARY,Windows 将对该文件的 '\n' 字符进行不同的处理.它可能在遇到的第一个 '\n' 处返回.

  3. 在读取文件之前没有必要检查文件大小.read() 以及任何围绕 read() 的包装器将始终在文件末尾停止读取.

更新0

进一步观察,我看到第 5 个和第 6 个字符是 \r\n,这是 Windows 在文本模式下专门处理的,并解释了我上面提到的早期返回.如果您不将 O_BINARY 传递给 open() 调用,这两个字符将被转换为单个 \n.

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.

解决方案

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.

这篇关于Windows 上的 read() 系统调用无法读取二进制文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆