在C中读/写二进制文件

use*_*114 52 c linux binary file-io

有没有人有一个可以写入二进制文件的代码示例.还有可以读取二进制文件并输出到屏幕的代码.查看示例我可以写入文件ok但是当我尝试从文件中读取时它没有正确输出.

Mik*_*ike 91

读取和写入二进制文件几乎与任何其他文件相同,唯一的区别是如何打开它:

unsigned char buffer[10];
FILE *ptr;

ptr = fopen("test.bin","rb");  // r for read, b for binary

fread(buffer,sizeof(buffer),1,ptr); // read 10 bytes to our buffer
Run Code Online (Sandbox Code Playgroud)

你说你可以读它,但它输出不正确...请记住,当你"输出"这些数据时,你不是在读ASCII,所以它不像在屏幕上打印一个字符串:

for(int i = 0; i<10; i++)
    printf("%u ", buffer[i]); // prints a series of bytes
Run Code Online (Sandbox Code Playgroud)

写入文件几乎是一样的,除了您使用fwrite()而不是fread():

FILE *write_ptr;

write_ptr = fopen("test.bin","wb");  // w for write, b for binary

fwrite(buffer,sizeof(buffer),1,write_ptr); // write 10 bytes from our buffer
Run Code Online (Sandbox Code Playgroud)

因为我们正在谈论Linux ..有一种简单的方法来进行健全性检查.hexdump在您的系统上安装(如果它还没有在那里)并转储您的文件:

mike@mike-VirtualBox:~/C$ hexdump test.bin
0000000 457f 464c 0102 0001 0000 0000 0000 0000
0000010 0001 003e 0001 0000 0000 0000 0000 0000
...
Run Code Online (Sandbox Code Playgroud)

现在将它与您的输出进行比较:

mike@mike-VirtualBox:~/C$ ./a.out 
127 69 76 70 2 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

嗯,也许改成printfa %x来使这个更清晰一些:

mike@mike-VirtualBox:~/C$ ./a.out 
7F 45 4C 46 2 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

你看!数据现在匹配*.太棒了,我们必须正确读取二进制文件!

*注意字节只是在输出上交换,但数据是正确的,你可以调整这种事情

  • 请注意,在Linux(以及基于Unix的系统)上,`b`标志是'可选'的 - 在这样的系统上,二进制文件和文本文件之间没有区别.不过,这种差异在Windows上非常重要.如果您的代码具有可移植性的前提条件,请在将文件视为二进制文件时添加`b`. (7认同)
  • 不要忘记`fclose(ptr);`! (4认同)
  • 在二进制模式下,“fread”函数在发现 CR 或 LF 字符时是否终止读取? (2认同)

Ala*_*rey 5

有几种方法可以做到这一点。如果我想读写二进制文件,我通常使用open(), read(), write(), close()。这与一次处理一个字节完全不同。您使用整数文件描述符而不是 FILE * 变量。fileno 将从 FILE * BTW 中获取一个整数描述符。您读取了一个充满数据的缓冲区,例如一次读取 32k 字节。缓冲区实际上是一个数组,您可以快速读取它,因为它位于内存中。一次读取和写入多个字节比一次读取和写入一个字节要快。我认为它在 Pascal 中称为块读取,但 read() 是 C 的等效项。

我查了一下,但没有任何方便的例子。好吧,这些并不理想,因为它们也在处理 JPEG 图像。这是一个阅读,您可能只关心从 open() 到 close() 的部分。fbuf 是要读入的数组,sb.st_size 是 stat() 调用中的文件大小(以字节为单位)。

    fd = open(MASKFNAME,O_RDONLY);
    if (fd != -1) {
      read(fd,fbuf,sb.st_size);
      close(fd);
      splitmask(fbuf,(uint32_t)sb.st_size); // look at lines, etc
      have_mask = 1;
    }
Run Code Online (Sandbox Code Playgroud)

这是一个写入:(这里 pix 是字节数组,jwidth 和 jheight 是 JPEG 宽度和高度,因此对于 RGB 颜色,我们写入 height * width * 3 个颜色字节)。这是要写入的字节数。

void simpdump(uint8_t *pix, char *nm) { // makes a raw aka .data file
  int sdfd;
  sdfd = open(nm,O_WRONLY | O_CREAT);
  if (sdfd == -1) {
    printf("bad open\n");
    exit(-1);
  }
  printf("width: %i height: %i\n",jwidth,jheight);  // to the console
  write(sdfd,pix,(jwidth*jheight*3));
  close(sdfd);
}
Run Code Online (Sandbox Code Playgroud)

看man 2打开,也读,写,关闭。还有这个旧式 jpeg example.c:https://github.com/LuaDist/libjpeg/blob/master/example.c 我在这里一次读取和写入整个图像。但它们是字节的二进制读写,只是一次很多。

“但是当我尝试从文件中读取时,它没有正确输出。” 嗯。如果你读到数字 65,它是 A 的(十进制)ASCII。也许你也应该看看 man ascii。如果您想要 1,则为 ASCII 0x31。char 变量实际上是一个很小的 ​​8 位整数,如果你执行 printf 作为 %i,你会得到 ASCII 值,如果你执行 %c,你会得到字符。对十六进制执行 %x。全部来自 0 到 255 之间的相同数字。