Linux 在 C 中读写二进制文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17598572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Read and write to binary files in C?
提问by user1257114
Does anyone have an example of code that can write to a binary file. And also code that can read a binary file and output to screen. Looking at examples I can write to a file ok But when I try to read from a file it is not outputting correctly.
有没有人有可以写入二进制文件的代码示例。还有可以读取二进制文件并输出到屏幕的代码。查看示例我可以写入文件 ok 但是当我尝试从文件中读取时,它没有正确输出。
回答by Mike
Reading and writing binary files is pretty much the same as any other file, the only difference is how you open it:
读取和写入二进制文件与任何其他文件几乎相同,唯一的区别是您打开它的方式:
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
You said you can read it, but it's not outputting correctly... keep in mind that when you "output" this data, you're not reading ASCII, so it's not like printing a string to the screen:
你说你可以读取它,但它没有正确输出......请记住,当你“输出”这个数据时,你不是在读取 ASCII,所以它不像在屏幕上打印字符串:
for(int i = 0; i<10; i++)
printf("%u ", buffer[i]); // prints a series of bytes
Writing to a file is pretty much the same, with the exception that you're using fwrite()
instead of fread()
:
写入文件几乎相同,除了您使用的是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:
既然我们在谈论 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
...
Now compare that to your output:
现在将其与您的输出进行比较:
mike@mike-VirtualBox:~/C$ ./a.out
127 69 76 70 2 1 1 0 0 0
hmm, maybe change the printf
to a %x
to make this a little clearer:
嗯,也许printf
将 a更改为%x
更清楚一点:
mike@mike-VirtualBox:~/C$ ./a.out
7F 45 4C 46 2 1 1 0 0 0
Hey, look! The data matches up now*. Awesome, we must be reading the binary file correctly!
你看!数据现在匹配*。太棒了,我们必须正确读取二进制文件!
*Note the bytes are just swapped on the output but that data is correct, you can adjust for this sort of thing
*注意字节只是在输出上交换,但数据是正确的,您可以针对此类事情进行调整
回答by Gregory Fenn
I'm quite happy with my "make a weak pin storage program" solution. Maybe it will help people who need a very simple binary file IO example to follow.
我对我的“制作弱引脚存储程序”解决方案非常满意。也许它会帮助那些需要一个非常简单的二进制文件 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;
}
$
回答by bpn
This is an example to read and write binary jjpg or wmv video file. FILE *fout; FILE *fin;
这是读取和写入二进制 jjpg 或 wmv 视频文件的示例。文件 *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);
回答by Isidoro gonzalez-adalid pemart
this questions is linked with the question How to write binary data file on C and plot it using Gnuplotby CAMILO HG. I know that the real problem have two parts: 1) Write the binary data file, 2) Plot it using Gnuplot.
这个问题与如何在 C 上编写二进制数据文件并使用CAMILO HG 的Gnuplot 绘制它的问题相关联。我知道真正的问题有两个部分:1) 编写二进制数据文件,2) 使用 Gnuplot 绘制它。
The first part has been very clearly answered here, so I do not have something to add.
第一部分在这里已经回答得很清楚了,所以我没有什么要补充的了。
For the second, the easy way is send the people to the Gnuplot manual, and I sure someone find a good answer, but I do not find it in the web, so I am going to explain one solution (which must be in the real question, but I new in stackoverflow and I can not answer there):
对于第二种,最简单的方法是将人们发送到 Gnuplot 手册,我确定有人找到了很好的答案,但我在网上找不到,所以我将解释一个解决方案(必须是真实的)问题,但我是 stackoverflow 的新手,我无法在那里回答):
After write your binary data file using fwrite()
, you should create a very simple program in C, a reader. The reader only contains the same structure as the writer, but you use fread()
instead fwrite()
. So it is very ease to generate this program: copy in the reader.c
file the writing part of your original code and change write for read (and "wb" for "rb"). In addition, you could include some checks for the data, for example, if the length of the file is correct. And finally, your program need to print the data in the standard output using a printf()
.
使用 编写二进制数据文件后fwrite()
,您应该用 C 语言创建一个非常简单的程序,即阅读器。请读者仅包含了相同的结构作家,但你用fread()
代替fwrite()
。因此,生成这个程序非常容易:将reader.c
原始代码的写入部分复制到文件中,并将写入更改为读取(将“wb”更改为“rb”)。此外,您可以对数据进行一些检查,例如,文件长度是否正确。最后,您的程序需要使用printf()
.
For be clear: your program run like this
明确一点:你的程序是这样运行的
$ ./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, with this program, in Gnuplot you only need to pipe the standard output of the reader to the Gnuplot, something like this:
好的,有了这个程序,在 Gnuplot 中,您只需要将阅读器的标准输出通过管道传输到 Gnuplot,如下所示:
plot '< ./reader data.dat'
This line, run the program reader, and the output is connected with Gnuplot and it plot the data.
这一行,运行程序阅读器,输出连接到 Gnuplot 并绘制数据。
*Because Gnuplot is going to read the output of the program, you must know what can Gnuplot read and plot and what can not.
*因为 Gnuplot 将读取程序的输出,所以您必须知道 Gnuplot 可以读取和绘制哪些内容,哪些不能。
回答by Alan
I really struggled to find a way to read a binary file into a byte array in C++ that would output the same hex values I see in a hex editor. After much trial and error, this seems to be the fastest way to do so without extra casts. By default it loads the entire file into memory, but only prints the first 1000 bytes.
我真的很难找到一种方法将二进制文件读入 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]);
}
回答by Alan Corey
There are a few ways to do it. If I want to read and write binary I usually use open(), read(), write(), close(). Which are completely different than doing a byte at a time. You work with integer file descriptors instead of FILE * variables. fileno will get an integer descriptor from a FILE * BTW. You read a buffer full of data, say 32k bytes at once. The buffer is really an array which you can read from really fast because it's in memory. And reading and writing many bytes at once is faster than one at a time. It's called a blockread in Pascal I think, but read() is the C equivalent.
有几种方法可以做到。如果我想读写二进制文件,我通常使用 open()、read()、write()、close()。这与一次执行一个字节完全不同。您使用整数文件描述符而不是 FILE * 变量。fileno 将从 FILE * BTW 获取整数描述符。您一次读取了一个充满数据的缓冲区,比如说 32k 字节。缓冲区实际上是一个数组,您可以非常快速地读取它,因为它在内存中。一次读取和写入多个字节比一次一个要快。我认为它在 Pascal 中称为 blockread,但 read() 是 C 等效项。
I looked but I don't have any examples handy. OK, these aren't ideal because they also are doing stuff with JPEG images. Here's a read, you probably only care about the part from open() to close(). fbuf is the array to read into, sb.st_size is the file size in bytes from a stat() call.
我看了,但我没有任何方便的例子。好吧,这些并不理想,因为它们也在处理 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;
}
Here's a write: (here pix is the byte array, jwidth and jheight are the JPEG width and height so for RGB color we write height * width * 3 color bytes). It's the # of bytes to write.
这是一个写:(这里的 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);
}
Look at man 2 open, also read, write, close. Also this old-style jpeg example.c: https://github.com/LuaDist/libjpeg/blob/master/example.cI'm reading and writing an entire image at once here. But they're binary reads and writes of bytes, just a lot at once.
看 man 2 打开,也读,写,关闭。还有这个旧式 jpeg example.c:https: //github.com/LuaDist/libjpeg/blob/master/example.c我在这里一次读取和写入整个图像。但它们是字节的二进制读取和写入,一次很多。
"But when I try to read from a file it is not outputting correctly." Hmmm. If you read a number 65 that's (decimal) ASCII for an A. Maybe you should look at man ascii too. If you want a 1 that's ASCII 0x31. A char variable is a tiny 8-bit integer really, if you do a printf as a %i you get the ASCII value, if you do a %c you get the character. Do %x for hexadecimal. All from the same number between 0 and 255.
“但是当我尝试从文件中读取时,它没有正确输出。” 嗯。如果你读到一个数字 65,它是 A 的(十进制)ASCII。也许你也应该看看 man ascii。如果你想要一个 1,那就是 ASCII 0x31。char 变量实际上是一个很小的 8 位整数,如果将 printf 作为 %i 执行,则会获得 ASCII 值,如果执行 %c 则获得字符。做 %x 十六进制。全部来自 0 到 255 之间的相同数字。