我对二进制文件有点困惑,我知道数据存储在二进制文件的块中,根据我的知识通过实验我发现如果我们有一个带有这样的成员变量的结构:
struct student{
int Roll_No;
char Name[10];
}
然后用内容更新变量并将其保存在二进制文件中后,二进制文件为14个字节,10个字节的char和4个int,所以如果我们在hexeditor中分析文件,则该文件有4个字节保留对于Roll_no和为Name填充的10个字节,其中填充的内容被填充,其他可以看作文件中的点,我的意思是如果我们创建一个带有上面结构/类的程序,并且在将内容保存到文件后,文件的size与我们创建的结构相同,我的意思是4个int和10个char,所以据我所知,如果我创建了一个新的图像格式,例如。 (点).MyIMG,来自我的程序,其结构/类是这样的
struct MyIMG{
char Header[5];
int width, height;
int Pixels[124000];
}
然后我的程序将创建一个大小为49613字节或49千兆字节的新文件(标题为5,+高度和宽度的+(加)8,+(加)4×124000的int像素),像素是4,8,100,或者它会写出整个像素阵列的空白,所以为什么这种效果在MSpaint,Adobe Photoshop等任何大型软件上都不一样,他们做了什么,这使得他们的程序编写的文件是大小取决于存储的像素而不是空白数组...
编辑:我现在已经编辑了我的问题,并清楚地定义了我的问题,请帮助我,提前谢谢!!答案 0 :(得分:2)
.png和.bmp等文件格式具有特定格式。文件格式可以指定字节布局(例如宽度为4个字节,高度为4个字节,RGBA像素数据为2MB,或者其他),或者格式可以为您提供有关各种对象大小的信息。
例如,TIFF文件将指定文件中特定字节偏移处的数字标记。然后,这些标签包含有关图像数据的大小,位置和格式的信息。因此,您可能有一个固定大小的标题,表示"标记列表从字节100开始,它包含40个标记。"标签每个都是固定大小(比如说16个字节),因此您可以从字节100开始读取40个16字节的块。然后标签将包含诸如开始的字节偏移之类的信息。图像数据,像素中有多少字节,以及有多少像素。通过这种方式,您可以在不事先知道整个格式的情况下读取数据。
答案 1 :(得分:1)
编写文件的代码必须选择自己的格式。例如,在将student
结构写入文件时,您可以说:
size_t name_len = strlen(my_student.Name);
my_ofstream.write((const char*)&my_student, sizeof my_student - sizeof my_student.Name + name_len + 1);
然后,这将把名称写入并包括第一个0 / NUL字符到二进制文件。当回读文件时,程序可以从ifstream
读取一个数据块 - 然后知道student
存储在某个偏移处,使用strlen()
上的.Name
部分传入数据以恢复长度,部分原因是它只能将必要的数据复制到student
对象,并且还知道从输入流开始解析下一个数据项的位置:
char buffer[32768];
student my_student;
if (my_ifstream.read(buffer, sizeof buffer) && my_ifstream.gcount() > 5)
{
// check for NUL without risking reading buffer[.gcount()]
size_t pre_name_len = std::offsetof(student, name);
const char* p_name = buffer + pre_name_len;
const char* p_nul = strnchr(p_name,
std::min(10, my_ifstream.gcount() - pre_name_len),
'\0');
if (p_nul == nullptr || *p_nul != '\0')
throw std::runtime_error("file didn't contain complete student record");
memcpy(my_student, buffer, p_nul - buffer + 1);
// keep parsing input from p_nul + 1, not going past .gcount()
}
正如您所看到的 - 扫描单个NUL同时跟踪从文件读取的数据量是一件很痛苦的事情,这样如果输入文件损坏,您就不会崩溃.... / p>
对于初学者来说,了解boost serialisation library可能是最容易和更强大的,它提取了大部分低级别的内容 - 有人会说C风格 - I / O,投射和偏移计算以提供更清洁逻辑接口。