我需要读取包含标题和数据的二进制文件(一次性)。有不同的方法来读取C ++文件,我想知道哪一个是最快,更可靠的。我也不知道reintrerpret_cast
是否是将原始数据转换为结构的最佳方式。
编辑:标题结构没有任何功能,只有数据。
ifstream File(Filename, ios::binary); // Opens file
if (!File) // Stops if an error occured
{
/* ... */
}
File.seekg(0, ios::end);
size_t Size = File.tellg(); // Get size
File.seekg(0, ios::beg);
这是ifstream WITHOUT istreambuf_iterator
char* Data = new char[Size];
File.read(Data, Size);
File.close();
HeaderType *header = reinterpret_cast<HeaderType*>(Data);
/* ... */
delete[] Data;
ifstream with istreambuf_iterator
std::string Data; // Is it better to use another container type?
Data.reserve(Size);
std::copy((std::istreambuf_iterator<char>(File)), std::istreambuf_iterator<char>(),
std::back_inserter(Data));
File.close();
const HeaderType *header = reinterpret_cast<HeaderType*>(Data.data());
也在互联网上找到了这个
std::ostringstream Data;
Data << File.rdbuf();
File.close();
std::string String = Data.str();
const HeaderType *header = reinterpret_cast<HeaderType*>(String.data());
答案 0 :(得分:3)
将文件内容读入char*
然后执行reinterpret_cast
至HeaderType*
并不是一个好主意。
来自标准:
5.2.10重新解释投射
...
7可以将对象指针显式转换为不同类型 70 的对象指针。当“指向
v
的指针”的prvalueT1
转换为“指向 cvT2
的指针”时,结果为static_cast<cv T2*>(static_cast<cv void*>(v))
如果T1
和T2
都是标准布局类型(3.9),并且T2
的对齐要求不比T1
更严格,或者任何一种类型都是{{} 1}}。将“指向void
”的类型的prvalue转换为“指向T1
”的类型(其中T2
和T1
是对象类型,{{T2
的对齐要求1}}不比T2
更严格,并且返回其原始类型会产生原始指针值。任何其他此类指针转换的结果都未指定。
在您的情况下,如果T1
的对齐要求比HeaderType
更严格,则会遇到未定义的行为。
如果您有选择,我建议。
首先阅读标题。
char
根据HeaderType header;
File.read(reinterpret_cast<char*>(&header), sizeof(HeaderType));
的值阅读其余数据。
答案 1 :(得分:1)
这将是基于意见的&#39;因此对于SO来说并非严格意义上的。
但是,在这种情况下我没有看到使用迭代器的重点,因为read()
函数更简洁。
然而,更重要的是,您执行此操作的方式会破坏严格的别名规则,因为struct
内存中的对齐不能保证与char
数组一致。
最好将struct
的地址转换为char*
,而不是相反:
HeaderType header;
File.read(reinterpret_cast<char*>(&header), sizeof(header));
File.close();
以这样的二进制方式读取数据是不可移植的,并且不适用于复杂的用户定义类型(如std::string
),因此最好将所有数据成员序列化为格式化字符串。
注意:有关类型别名的信息,请参阅reinterpret_cast的文档。
答案 2 :(得分:0)
首先,您描述的解决方案都不会真正起作用;该
reinterpret_cast
应该告诉你。在某些时候,你必须这样做
解析缓冲区中的字节,并插入提取的数据字段
字段到您的内部数据结构。
至于尽快将字节输入缓冲区,
你做的额外工作越少越好。最快的方法是
在Unix下使用低级IO(open
然后read
),甚至映射
将文件存入内存(Unix下为mmap
)。当然,这是系统
依赖;如果你想使用ifstream
来实现系统
独立性,然后使用istream::read
肯定是最快的(和
最符合逻辑的,所有事情都考虑在内)。只要确定流
充满了"C"
语言环境,以及以二进制模式打开。
对于记录:使用系统级功能将传输数据
直接从OS进入缓冲区。 istream::read
将从中复制
filebuf
中的内部缓冲区进入缓冲区(并使用系统
级别函数将数据输入缓冲区)。另外两个会
逐个字节地构建一个std::string
对象,将内存分配为
需要,因为最后的长度将不知道。
最后,使用new char[size]
而不是std::vector<char>
。