提问者:小点点

读写C中的二进制文件?


有人有一个可以写入二进制文件的代码示例吗?还有可以读取二进制文件并输出到屏幕的代码。看例子,我可以写入文件,好吧,但是当我尝试从文件中读取时,输出不正确。


共3个答案

匿名用户

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

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

你说你可以读取它,但它没有正确输出…请记住,当您“输出”此数据时,您没有读取ASCII,因此这不像将字符串打印到屏幕上:

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

写入文件几乎是一样的,除了您使用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

既然我们在谈论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
...

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

mike@mike-VirtualBox:~/C$ ./a.out 
127 69 76 70 2 1 1 0 0 0

嗯,也许可以将printf更改为%x以使其更清晰:

mike@mike-VirtualBox:~/C$ ./a.out 
7F 45 4C 46 2 1 1 0 0 0

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

*请注意,字节只是在输出上交换,但数据是正确的,您可以针对这种情况进行调整

匿名用户

有几种方法可以做到这一点。如果我想读写二进制文件,我通常使用open()read()write()over()。这与一次处理一个字节完全不同。你使用整数文件描述符而不是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;
    }

这里是一个写入:(这里pix是字节数组,jwide和j高是JPEG的宽度和高度,所以对于RGB颜色,我们写入高度*宽度*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);
}

看看man 2 open,也读,写,关闭。还有这个老式的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之间的同一个数字。

匿名用户

我对我的“制作一个弱pin存储程序”解决方案很满意。也许它会帮助那些需要一个非常简单的二进制文件的人IO例子。

$ ls
WeakPin  my_pin_code.pin  weak_pin.c
$ ./WeakPin
Pin: 45 47 49 32
$ ./WeakPin 8 2
$ Need 4 ints to write a new pin!
$./WeakPin 8 2 99 49
Pin saved.
$ ./WeakPin
Pin: 8 2 99 49
$
$ cat weak_pin.c
// a program to save and read 4-digit pin codes in binary format

#include <stdio.h>
#include <stdlib.h>

#define PIN_FILE "my_pin_code.pin"

typedef struct { unsigned short a, b, c, d; } PinCode;


int main(int argc, const char** argv)
{
    if (argc > 1)  // create pin
    {
        if (argc != 5)
        {
            printf("Need 4 ints to write a new pin!\n");
            return -1;
        }
        unsigned short _a = atoi(argv[1]);
        unsigned short _b = atoi(argv[2]);
        unsigned short _c = atoi(argv[3]);
        unsigned short _d = atoi(argv[4]);
        PinCode pc;
        pc.a = _a; pc.b = _b; pc.c = _c; pc.d = _d;
        FILE *f = fopen(PIN_FILE, "wb");  // create and/or overwrite
        if (!f)
        {
            printf("Error in creating file. Aborting.\n");
            return -2;
        }

        // write one PinCode object pc to the file *f
        fwrite(&pc, sizeof(PinCode), 1, f);  

        fclose(f);
        printf("Pin saved.\n");
        return 0;
    }

    // else read existing pin
    FILE *f = fopen(PIN_FILE, "rb");
    if (!f)
    {
        printf("Error in reading file. Abort.\n");
        return -3;
    }
    PinCode pc;
    fread(&pc, sizeof(PinCode), 1, f);
    fclose(f);

    printf("Pin: ");
    printf("%hu ", pc.a);
    printf("%hu ", pc.b);
    printf("%hu ", pc.c);
    printf("%hu\n", pc.d);
    return 0;
}
$