用 C 语言读写二进制文件?

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

411245 次浏览

读写二进制文件和其他文件几乎没有什么区别,唯一的区别在于你如何打开它:

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

Since we're talking Linux.. there's an easy way to do a sanity check. Install hexdump on your system (if it's not already on there) and dump your file:

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

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

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

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

这是一个读写二进制 jjpg 或 wmv 视频文件的示例。 FILE * fout; 文件 * 鳍;

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);

这个问题与 CAMILO HG 的问题 如何在 C 上编写二进制数据文件,并使用 Gnuplot 绘制它有关。我知道真正的问题有两部分: 1)编写二进制数据文件,2)使用 Gnuplot 绘制它。

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

第二,简单的方法是把人们发送到 Gnuplot 手册,我确信有人找到了一个好的答案,但我没有在网上找到它,所以我要解释一个解决方案(这必须是在真正的问题,但我新的堆栈溢出,我不能在那里回答) :

在使用 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


好的,在 Gnuplot,使用这个程序,你只需要将阅读器的标准输出通过管道传输到 Gnuplot,大概是这样的:

plot '< ./reader data.dat'

这一行运行程序阅读器,输出与 Gnuplot 连接,它绘制数据。

* 因为 Gnuplot 要读取程序的输出,所以必须知道哪些内容可以读取和绘图,哪些内容不可以。

我真的很难找到一种方法,在 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]);
}

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

我找过了,但手边没有任何例子。好的,这些并不理想,因为它们也在用 JPEG 图像做东西。这里有一个阅读,您可能只关心从 open ()到 close ()的部分。Fbuf 是要读入的数组, 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;
}

这里是一个 write: (这里的 pix 是字节数组,jwidth 和 jheight 是 JPEG 的 width 和 height,所以对于 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);
}

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

“但是当我试图从文件中读取时,它不能正确地输出。”嗯。如果你读了一个数字65,这是(十进制) ASCII 的 A。也许你也应该看看人的 ASCII。如果你想要1那就是 ASCII 0x31。一个 char 变量实际上是一个很小的8位整数,如果你把 printf 作为% i,你会得到 ASCII 值,如果你做% c,你会得到字符。对十六进制执行% x。都来自同一个数字,介于0和255之间。

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


main(int argc, char **argv) //int argc; char **argv;
{
int wd;
FILE *in, *out;


if(argc != 3) {
printf("Input and output file are to be specified\n");
exit(1);
}
in = fopen(argv[1], "rb");
out = fopen(argv[2], "wb");
if(in == NULL || out == NULL) { /* open for write */
printf("Cannot open an input and an output file.\n");
getchar();
exit(0);
}
while(wd = getw(in), !feof(in)) putw(wd, out);


fclose(in);
fclose(out);


}