【问题标题】:write std::bitset to binary file and load the file to std:bitset将 std::bitset 写入二进制文件并将文件加载到 std:bitset
【发布时间】:2016-07-19 08:57:55
【问题描述】:

我正在处理一个将使用 bitset 的项目。由于提供的文本文件非常大(>800M),将其直接加载到 std::bitset 将花费超过 25 秒。所以我想将文本文件预处理为内存转储的二进制文件。 因为 8 位 char 会转换为 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;
}

看起来工作正常,但我担心这种用法在生产环境中真的可以正常工作。

感谢一些高级。

【问题讨论】:

  • std::bitset&lt;MAX_SIZE&gt;* foo = new (std::nothrow)std::bitset&lt;MAX_SIZE&gt;(line); -- 为什么要在这里动态分配?当您将指针 (&amp;foo) 的地址提供给 os.write 时,我看不出这是如何“正常”工作的。
  • 由于提供的文本文件非常大(>800M),将其直接加载到 std::bitset 将花费 25 秒以上。 -- 你有一个非常如果是这样的话,磁盘系统很差。

标签: c++ std-bitset


【解决方案1】:

将二进制非平凡类写入文件确实很危险。您应该将 bitset 转换为明确定义的二进制数据。如果您知道您的数据适合 unsigned long long,则可以使用 bitset::to_ullong() 并写入/读取该 unsigned long long。如果您希望这是跨平台的甜菜,例如64 位和 32 位平台,您应该使用固定大小的类型。

【讨论】:

    【解决方案2】:

    这两行是错误的

    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::bitsetPODtype 并按此方式访问它。但是,当您的代码变得更加复杂时,您就有编写或阅读过多的风险,并且没有任何保护措施可以阻止未定义行为的发生。 std::bitset 是为了方便而不是快速,它通过它提供的访问位的方法来表达 - 没有适当的方法来获取其存储地址,例如,std::vectorstd::string 提供.如果您需要性能,则需要自己实现。

    【讨论】:

    • 代码错误。指针foofoo2的地址正在传递,这是错误的。
    • @zhouhongwei 回答接受是stackoverflow的一种表示感谢的方式:)
    猜你喜欢
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多