我正在使用一个将使用bitset的项目。由于提供的文本文件非常大(> 800M),将其直接加载到std :: bitset将花费超过25秒。所以我想将文本文件预处理为内存转储二进制文件。 因为8位的字符将转换为1位,所以文件加载的成本时间将减少很多。我写了一个演示代码:
#include <iostream>
#include <bitset>
#include <string>
#include <stdexcept>
#include <fstream>
#include <math.h>
int main () {
const int MAX_SIZE = 19;
try {
std::string line = "1001111010011101011";
int copy_bypes = (int)ceil((float)MAX_SIZE / 8.0);
std::bitset<MAX_SIZE>* foo = new (std::nothrow)std::bitset<MAX_SIZE>(line); // foo: 0000
std::ofstream os ("data.dat", std::ios::binary);
os.write((const char*)&foo, copy_bypes);
os.close();
std::bitset<MAX_SIZE>* foo2 = new (std::nothrow)std::bitset<MAX_SIZE>();
std::ifstream input("data.dat",std::ios::binary);
input.read((char*)&foo2, copy_bypes);
input.close();
for (int i = foo2->size() -1 ; i >=0 ; --i) {
std::cout << (*foo2)[i];
}
std::cout <<std::endl;
}
catch (const std::invalid_argument& ia) {
std::cerr << "Invalid argument: " << ia.what() << '\n';
}
return 0;
}
它似乎工作正常,但我担心这种用法在生产环境中确实可以正常工作。
先谢谢了。
答案 0 :(得分:0)
将二进制非trival类写入文件非常危险。您应该将bitset转换为定义良好的二进制数据。如果您知道您的数据适合无符号long long,则可以使用bitset&lt;&gt; :: to_ullong()并写入/读取unsigned long long。如果你想这是跨平台beetwet,例如在64位和32位平台上,您应该使用固定大小的类型。
答案 1 :(得分:0)
这两行错误
os.write((const char*)&foo, copy_bypes);
input.read((char*)&foo2, copy_bypes);
您将指针的地址传递给foo2
,而不是std::bitset
对象本身。但即使它得到了纠正:
os.write((const char*)foo, copy_bypes);
input.read((char*)foo2, copy_bypes);
在生产环境中使用会不安全。在此,您假设std::bitset
是PODtype,并按此访问它。但是,当您的代码变得更加复杂时,您将面临写作或阅读过多的风险,并且没有任何保护措施可以阻止未定义的行为发生。 std::bitset
被认为是方便的,而不是快速的,它通过它提供的访问位的方法来表达 - 没有正确的方法来获取其存储的地址,例如,{std::vector
1}}或std::string
提供。如果您需要表现,您需要自己实施。