最近有人要求我编写一个函数,将二进制文件读入 std::vector<BYTE>
其中 BYTE
是一个 unsigned char
。很快我就得到了这样的东西:
#include <fstream>
#include <vector>
typedef unsigned char BYTE;
std::vector<BYTE> readFile(const char* filename)
{
// open the file:
std::streampos fileSize;
std::ifstream file(filename, std::ios::binary);
// get its size:
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// read the data:
std::vector<BYTE> fileData(fileSize);
file.read((char*) &fileData[0], fileSize);
return fileData;
}
这似乎是不必要的复杂,而且我在调用 file.read
时被迫使用的 char*
的显式转换并没有让我感觉更好。
另一种选择是使用 std::istreambuf_iterator
:
std::vector<BYTE> readFile(const char* filename)
{
// open the file:
std::ifstream file(filename, std::ios::binary);
// read the data:
return std::vector<BYTE>((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
}
这是非常简单和简短的,但我仍然必须使用 std::istreambuf_iterator<char>
即使我正在阅读 std::vector<unsigned char>
。
最后一个似乎非常简单的选项是使用 std::basic_ifstream<BYTE>
,这有点明确表示 “我想要一个输入文件流,我想用它来读取 BYTE
s” :
std::vector<BYTE> readFile(const char* filename)
{
// open the file:
std::basic_ifstream<BYTE> file(filename, std::ios::binary);
// read the data:
return std::vector<BYTE>((std::istreambuf_iterator<BYTE>(file)),
std::istreambuf_iterator<BYTE>());
}
但我不确定 basic_ifstream
在这种情况下是否合适。
将二进制文件读入 vector
的最佳方法是什么? 我还想知道 “幕后”发生了 什么以及我可能遇到的可能问题是什么(除了没有正确打开流,这可以通过简单的 is_open
检查来避免)。
有什么好的理由可以在这里使用 std::istreambuf_iterator
吗?
(我能看到的唯一优点是简单)
原文由 LihO 发布,翻译遵循 CC BY-SA 4.0 许可协议
在测试性能时,我会包括一个测试用例:
我的想法是方法 1 的构造函数触及
vector
中的元素,然后read
再次触及每个元素。方法 2 和方法 3 看起来最有希望,但可能会遭受一个或多个
resize
的影响。因此,在读取或插入之前要reserve
的原因。我还将使用
std::copy
进行测试:最后,我认为最好的解决方案是避免来自
operator >>
的istream_iterator
(以及来自operator >>
尝试解释二进制数据的所有开销和优点)。但我不知道使用什么可以让您直接将数据复制到向量中。最后,我对二进制数据的测试显示
ios::binary
没有被兑现。因此noskipws
来自<iomanip>
的原因。