c++ - 将二进制文件缓冲区的 block 读入不同类型

标签 c++ storage binaryfiles data-access

我正在尝试将二进制文件读入内存,然后像这样使用它:

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。它有一个指向实际数据的指针。

字节顺序。
对于多字节整数,一些处理器喜欢最高有效字节 (MSB),又名 Big Endian,首先(人类读取数字的方式)或最低有效字节优先,又名 Little Endian。 Little Endian 格式比 Big Endian 格式需要更少的电路来读取。

编辑 2:变体记录

当输出数组和容器之类的东西时,您必须决定是要输出整个容器(包括未使用的槽)还是只输出容器中的项目。仅输出容器中的项目将使用变体记录 技术。

输出变体记录的两种技术:数量后跟元素或元素后跟标记。后者是 C 风格字符串的编写方式,标记是空字符。

另一种技术是输出项目的数量,然后是项目。所以如果我有 6 个数字,0、1、2、3、4、5,输出将是:
6//项目数
0
1
2
3
4
5

在上面的 Load_From_Buffer 方法中,我将创建一个临时文件来保存数量,将其写出,然后跟从容器中的每个项目。

关于c++ - 将二进制文件缓冲区的 block 读入不同类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14591164/

相关文章:

C++ - 如何将 char* 转换为 std::list<char>

C++:从具有空字符的文件中读取

c++ - 错误: Expected a qualified name after 'typename' C++

java - 如何在Android SD卡中创建隐藏文件夹并向其推送内容

git - git 的大文件扩展

javascript - 如何在 javascript 中读取二进制文件(xml 样式)?

c++ - 如何轻松检测字符串中的utf8编码?

android - 共享首选项不起作用,android?

c# - 从关系数据库的角度开始使用 Azure 存储

python - 用python制作查找表,写入可以在C程序中读取的二进制文件