正在追加二进制文件

Appending Binary files

本文关键字:二进制文件 追加      更新时间:2023-10-16

我必须将数字数据写入二进制文件。由于我处理的一些数据向量的大小可能是几GB,所以我学会了不使用C++iostream。相反,我想使用C文件*。我马上就遇到了一个问题,我需要在二进制文件的前面写一些元数据。由于一些元数据一开始是未知的,我需要在获得元数据时将其附加到文件中适当的偏移量。

例如,假设我必须输入年份、月份和日期的uint16_t表示,但首先我需要跳过第一个条目(精度为uint32_t值);

我不知道我做错了什么,但我似乎无法在文件中添加"ab"。下面是我写的一个例子:

#include<cstdio>
uint16_t year = 2001;
uint16_t month = 8;
uint16_t day = 23;
uint16_t dateArray[]={year , month, day};
File * fileStream;
fileStream = fopen("/Users/mmmmmm/Desktop/test.bin" , "wb");
if(fileStream){
// skip the first 4 bytes
fseek ( fileStream , 4 , SEEK_SET );
fwrite(dateArray, sizeof(dateArray[0]) ,( sizeof(dateArray) / sizeof(dateArray[0]) ), filestream);
fclose(filestream);
}
 // loops and other code to prepare and gather other parameters

//现在以精确的精度附加到文件的前面。

uint32_t precision = 32;
File *fileStream2;
fileStream2 = fopen("/Users/mmmmmm/Desktop/test.bin" , "ab"); 
if(fileStream2){
// Get to the top of the file
rewind(fileStream2);
fwrite(&precision, sizeof(precision) , 1 , fileStream2);
fclose(fileStream2);
}

附加的数据不写入。如果我将其更改为"wb",则文件将被覆盖。我能够让它与"r+b"一起工作,但我不明白为什么。我认为"ab"是恰当的。此外,我应该使用缓冲区还是这是一种足够的方法?

感谢的建议

顺便说一句,这是在MacOSX 上

由于硬盘驱动器和文件系统的工作方式,在文件中间插入字节确实很慢,应该避免,尤其是在处理千兆字节的文件时。如果您的元数据存储在固定大小的标头中,那么在开始处理其他数据之前,只需确保有足够的空间即可。如果标头大小可变,则对标头进行分块。将1k的标头空间放在开头,并保留8个字节以包含到下一个标头块的偏移值,或者0表示EOF。然后,当这个块被填满时,只需在文件的末尾添加另一个块,并将其偏移量写入前一个标头。

对于技术IO,根据需要使用r+bw+ba+bfopen()模式。他们的行为都一样,只是略有不同。r+b打开文件进行读取和写入,从第一个字节开始。如果文件不存在,它将出错。w+b也会执行同样的操作,但如果文件不存在,则创建该文件。a+br+b相同,但它从文件末尾的文件指针开始。

您可以使用fseek()rewind()导航文件。rewind()将文件指针移回文件的开头。fseek()将文件指针移动到指定位置。你可以在这里阅读更多关于它的信息。

"r+b"意味着您可以读取和写入文件中的任何位置。在第二个代码块中,rewind()调用将当前位置设置为字节0,并在该位置完成写入。

如果使用"a+b",这也意味着读取和写入访问,但写入都在文件的末尾,因此除非创建新的空文件,否则无法定位在字节0。

要重新访问特定字节的文件,只需使用fseek()。

fseek(fileStream,0,SEEK_SET);-位置到精度值

fseek(fileStream,4,SEEK_SET);-头寸对年价值

fseek(fileStream,8,SEEK_SET);-仓位到月值

fseek(fileStream,12,SEEK_SET);-仓位到日值

对于如此大的文件,只为准备几个字节而重写gig将是非常低效的。

最好为每个文件创建一个包含所需元数据的小配套文件,如果要在编辑过程中重写元数据字段,则只在文件的开头添加元数据字段。

这是因为在大多数文件系统中,为文件做准备是非常昂贵的。NTFS为大多数文件提供了第二个数据通道,除了文件管理器和安全扫描程序等MS内部程序外,几乎所有程序都看不到该通道。您可以很容易地编写一个程序,将您的元数据添加到该频道,而无需每次都覆盖磁盘上的演出。