我试图将一个二进制文件读入内存,然后像这样使用它:
struct myStruct {
std::string mystring; // is 40 bytes long
uint myint1; // is 4 bytes long
};
typedef unsigned char byte;
byte *filedata = ReadFile(filename); // reads file into memory, closes the file
myStruct aStruct;
aStruct.mystring = filedata.????
我需要一种使用偏移量访问二进制文件并在该偏移量处获得一定长度的方法。
如果我将二进制文件数据存储在std::string中,这很容易,但是我发现使用二进制文件数据存储二进制数据并不是处理问题的好方法。
(filedata.substr(offset, len))
进行合理的广泛(IMO)搜索并没有找到任何相关的想法?如果您认为有必要,我愿意更改存储类型(例如,更改为std::vector)。
最佳答案
如果您不打算使用序列化库,那么我建议为每个类添加序列化支持:
struct My_Struct
{
std::string my_string;
unsigned int my_int;
void Load_From_Buffer(unsigned char const *& p_buffer)
{
my_string = std::string(p_buffer);
p_buffer += my_string.length() + 1; // +1 to account for the terminating nul character.
my_int = *((unsigned int *) p_buffer);
p_buffer += sizeof(my_int);
}
};
unsigned char * const buffer = ReadFile(filename);
unsigned char * p_buffer = buffer;
My_Struct my_variable;
my_variable.Load_From_Buffer(p_buffer);
其他一些有用的接口(interface)方法:
unsigned int Size_On_Stream(void) const; // Returns the size the object would occupy in the stream.
void Store_To_Buffer(unsigned char *& p_buffer); // Stores object to buffer, increments pointer.
使用模板,您可以扩展序列化功能:
void Load_From_Buffer(std::string& s, unsigned char *& p_buffer)
{
s = std::string((char *)p_buffer);
p_buffer += s.length() + 1;
}
void template<classtype T> Load_From_Buffer(T& object, unsigned char *& p_buffer)
{
object.Load_From_Buffer(p_buffer);
}
编辑1:不直接编写结构的原因
在C和C++中,结构的大小可能不等于其成员大小的总和。
允许编译器在成员之间插入填充或未使用的空间,以使成员在地址上对齐。
例如,一个32位处理器喜欢在4字节边界上获取内容。如果在结构中包含一个
char
,然后再添加一个int
,则会使int
位于相对地址1上,而不是4的倍数。编译器将填充该结构,以便int
在相对地址4上对齐。结构可以包含指针或包含指针的项目。
例如,
std::string
类型的大小可能为40,尽管字符串可能包含3个字符或300。它具有指向实际数据的指针。Endianess。
使用多字节整数时,某些处理器(例如,最高有效字节(MSB),也就是大字节序,首先(人类读取数字的方式),或者是最低有效字节,首先是小字节序(Little Endian)。 Little Endian格式比Big Endian所需的电路读取更少。
编辑2:变体记录
输出数组和容器之类的东西时,必须决定是要输出完整的容器(包括未使用的插槽)还是仅输出容器中的项目。仅输出容器中的项目将使用变体记录技术。
输出变体记录的两种技术:数量后跟项目或项目后跟哨兵。后者是C风格字符串的写法,前哨是nul字符。
另一种技术是输出项目数量,然后输出项目。因此,如果我有6个数字,分别为0、1、2、3、4、5,则输出为:
6 //项目数
0
1个
2
3
4
5
在上面的Load_From_Buffer方法中,我将创建一个临时数量来保存数量,将其写出,然后再处理容器中的每个项目。