我有一些文件* fp,它在数组中以文件标题“header”之后的4个字节的偏移量布局。
如何使用类型转换仅使用内存中的位置从该数组中读取单个结构?
会是这样的吗?
struct_name *arr = (struct_name *) &header + 4;
struct_name x = arr[1];
我正在做类似但却出现分段错误。有什么需要在这里进行malloc-ed?
答案 0 :(得分:0)
该文件需要加载到内存中,为了能够将此内存转换为结构,您有两个常用选项
boost::iostreams::mapped_file
映射文件(示例代码中的C ++版本)。在C中,您可以使用特定于平台的功能(Linux中为mmap,Windows中为CreateFileMapping和MapViewOfFile。)注意:要编译的struct的所有元素类型的大小必须在编译时知道(没有std :: string,或者在运行时分配内存的任何其他类型)。您需要在缓冲区中加载至少数组的内存以进行强制转换和迭代。
示例代码(使用C ++ 11在GCC 4.9.0中测试):
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <boost/iostreams/device/mapped_file.hpp>
struct data {
int a, b;
};
int main() {
// C version
FILE* fp = fopen("E:\\save.txt", "rb");
if (!fp)
return -1;
fseek(fp, 0L, SEEK_END);
int size0 = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char* cbuffer = (char*)malloc(size0);
fread(cbuffer, 1, size0, fp);
fclose(fp);
for (unsigned int idx = 0; idx < size0; idx++)
std::cout << (long)cbuffer[idx] << ",";
std::cout << std::endl;
data* data0 = (data*)&cbuffer[0];
for (int i = 0; i < 2; i++) {
std::cout << std::hex << data0[i].a << std::endl;
}
delete cbuffer;
// End C version
// C++ Version
std::ifstream ifs("E:\\save.txt", std::ios_base::binary | std::ios_base::in);
if (!ifs.good())
return -1;
ifs.seekg(0, std::ios_base::end);
long long size = ifs.tellg();
std::vector<unsigned char> buffer(size);
ifs.seekg(0, std::ios_base::beg);
ifs.read((char*)&buffer[0], buffer.size());
ifs.close();
for (auto d : buffer)
std::cout << (long)d << ",";
std::cout << std::endl;
data* data1 = (data*)&buffer[0];
for (int i = 0; i < 2; i++) {
std::cout << std::hex << data1[i].a << std::endl;
}
// End C++ Version
// C++ Mapped File
boost::iostreams::mapped_file mmfile("E:\\save.txt");
for (unsigned int idx = 0; idx < mmfile.size(); idx++)
std::cout << (long)mmfile.data()[idx] << ",";
std::cout << std::endl;
data* data2 = (data*)mmfile.data();
for (int i = 0; i < 2; i++) {
std::cout << std::hex << data2[i].b << std::endl;
}
mmfile.close();
// End C++ Mapped File
return 0;
}
答案 1 :(得分:0)
你问题中的(struct_name*)&header
意味着一种根本的误解。
除非这个变量存储文件的整个数据(而不仅仅是标题),否则使用它的地址可能是一个非常糟糕的主意,因为其余数据不会出现在&#34;之后#34; ;
因此,下面的答案假设您已将整个文件读入char* data
所指向的内存中。
理论上,你可以这样做:
element_struct val;
element_struct* ptr = (element_struct*)(data+sizeof(header_struct)+4);
// Read the n-th element (starting from 0)
val = ptr[n];
但是,由于未对齐的内存访问操作,这可能是不安全的。
因此,这是一种更安全的方法:
element_struct val;
char* ptr = data+sizeof(header_struct)+4;
// Read the n-th element (starting from 0)
memcpy(&val,ptr+n*sizeof(element_struct),sizeof(element_struct));
除了上述内容之外,您还需要确保编译器添加到结构中的填充,准确反映了数据在文件中的布局方式。