我想在使用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和我的图形库一起使用之前,我只需要将文件缓冲区放入内存中。
答案 0 :(得分:5)
几点:
read()
无法保证读取指定的字节数。它可能提前返回或根本不返回。必须多次调用read()
来填充大缓冲区是正常的。这是stdio包装器和fread()
有用的原因之一。
在Windows上,文本和二进制模式不同。由于您未在标志中指定O_BINARY
,因此Windows将以不同方式处理此文件的'\n'
个字符。可能它会在遇到的第一个'\n'
时返回。
在读取文件之前无需检查文件大小。 read()
以及read()
周围的任何包装将始终在文件末尾停止读取。
进一步观察我发现第5和第6个字符是\r\n
,这是在文本模式下由Windows专门处理的,并解释了我在上面提到的早期返回。如果您未将O_BINARY
传递给open()
来电,则这2个字符将转换为单个\n
。