在C中读/写二进制文件

时间:2013-07-11 16:19:45

标签: c linux file-io binary

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

6 个答案:

答案 0 :(得分:80)

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

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
嘿,看!数据现在匹配 * 。太棒了,我们必须正确读取二进制文件!

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

答案 1 :(得分:1)

有几种方法可以做到这一点。如果我想读写二进制文件,我通常使用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;
    }

这里是一个写操作:(这里pix是字节数组,jwidth和jheight是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);
}

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

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

答案 2 :(得分:0)

这是读取和写入二进制jjpg或wmv视频文件的示例。     FILE * fout;     文件* fin;

Int ch;
char *s;
fin=fopen("D:\\pic.jpg","rb");
if(fin==NULL)
     {  printf("\n Unable to open the file ");
         exit(1);
      }

 fout=fopen("D:\\ newpic.jpg","wb");
 ch=fgetc(fin);
       while (ch!=EOF)
             { 
                  s=(char *)ch;
                  printf("%c",s);
                 ch=fgetc (fin):
                 fputc(s,fout);
                 s++;
              }

        printf("data read and copied");
        fclose(fin);
        fclose(fout);

答案 3 :(得分:0)

此问题与CAMILO HG的问题How to write binary data file on C and plot it using Gnuplot相关联。我知道真正的问题有两个部分:1)编写二进制数据文件,2)使用Gnuplot对其进行绘图。

第一部分在这里已经很清楚地回答了,所以我没有什么要补充的。

第二,简单的方法是将人员发送到Gnuplot手册,我敢肯定有人找到了很好的答案,但是我在网上找不到,所以我将解释一个解决方案(必须是在真正的问题中,但是我是stackoverflow的新手,我无法在那里回答):

使用fwrite()编写二进制数据文件后,应使用C语言(阅读器)创建一个非常简单的程序。阅读器仅包含与编写器相同的结构,但是您使用fread()代替fwrite()。因此,生成该程序非常容易:在reader.c文件中复制原始代码的写入部分,然后将write更改为read(将“ wb”更改为“ rb”)。此外,您可以对数据进行一些检查,例如,文件长度是否正确。最后,您的程序需要使用printf()在标准输出中打印数据。

请注意:您的程序运行如下

$ ./reader data.dat

X_position Y_position  (it must be a comment for Gnuplot)*

1.23 2.45

2.54 3.12

5.98 9.52

Okey,使用此程序,在Gnuplot中,您只需要将阅读器的标准输出通过管道传输到Gnuplot,就像这样:

plot '< ./reader data.dat'

这行代码,运行程序读取器,输出与Gnuplot连接并绘制数据。

*由于Gnuplot将要读取程序的输出,因此您必须知道Gnuplot可以读取和绘制哪些内容,哪些不可以。

答案 4 :(得分:0)

我真的很难找到一种方法来将二进制文件读入C ++的字节数组中,以输出与十六进制编辑器中看到的相同的十六进制值。经过反复试验,这似乎是无需额外强制转换的最快方法。默认情况下,它将整个文件加载到内存中,但仅打印前1000个字节。

string Filename = "BinaryFile.bin";
FILE* pFile;
pFile = fopen(Filename.c_str(), "rb");
fseek(pFile, 0L, SEEK_END);
size_t size = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
uint8_t* ByteArray;
ByteArray = new uint8_t[size];
if (pFile != NULL)
{
    int counter = 0;
    do {
        ByteArray[counter] = fgetc(pFile);
        counter++;
    } while (counter <= size);
    fclose(pFile);
}
for (size_t i = 0; i < 800; i++) {
    printf("%02X ", ByteArray[i]);
}

答案 5 :(得分:-1)

我对我的“制作弱密码存储程序”解决方案感到非常满意。也许它将帮助那些需要一个非常简单的二进制文件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;
}
$