随时压缩/解压缩数据

时间:2014-01-15 12:00:19

标签: c++ compression

我正在运行物理模拟,我想改进它处理数据的方式。我正在保存并读取包含一个浮点数然后两个整数的文件,然后是512 * 512 = 262144 +1或-1,最后每个数据文件加权595 kb。所有这些数字都由一个空格分隔。

我正在保存数十万个这样的文件,所以它很快就会增加存储量的gigas,我想知道是否有一种快速(希望轻松的cpu-effort-wise方式)压缩和解压缩这种类型随时可用的数据(我的意思是在使用之前/之后没有使用)。

我到底能节省多少钱?

4 个答案:

答案 0 :(得分:4)

如果你想要相对快速的读写,你可能想要以“二进制”格式存储和读取它们,即它们以字节内部存储的方式本机。浮点数使用4个字节的数据,存储大量数据时不需要任何“分隔符”。

为此,您可以考虑boost's "serialize" library

请注意,使用数据压缩方法(zlib等)可以节省您存储的字节数,但压缩和解压缩它们的速度相对较慢。

以二进制格式存储不仅会占用较少的磁盘存储空间(比以文本格式存储),而且还应该更高性能,不仅因为文件I / O较少,而且还因为没有字符串写入/解析

请注意,当您输入/输出到binary_iarchivebinary_oarchive时,您会传入基础istreamostream,如果这是一个文件,则需要将其打开带有ios::binary标志,因为可能转换了行结尾的问题。

即使您确定数据压缩(zlib或其他库)是可行的方法,仍然值得使用boost :: serialize将数据转换为“blob”进行压缩。在这种情况下,您可能会使用std::ostringstream作为输出流来创建blob。

顺便提一下,如果你有2 ^ 18个“boolean”值只能是1或-1,那么每个只需1位,(它们将物理存储为1或0,但你会在逻辑上翻译它) 。那将是2 ^ 15字节,这是32K而不是595K

答案 1 :(得分:1)

鉴于有关有效数据的额外信息,请按以下方式定义您的类: -

class Data
{
  float m_float_value;
  int m_int_value_1, m_int_value_2;
  unsigned m_weights [8192];
};

然后使用二进制文件IO将此类传入和传出文件,不要转换为文本!

权重存储为布尔值,打包成无符号整数。

要获得权重,请添加一个访问者: -

int Data::GetWeight (size_t index)
{
  return m_weights [index >> 5] & (1 << (index & 31)) ? 1 : -1;
}

如果类数据中没有打包,这将为您提供32780字节(5.4%)的数据文件。

答案 2 :(得分:0)

我建议如果你担心大小,二进制格式将是“压缩”你的数据最有用的方法。听起来你正在处理以下内容:

struct data {
    float a;
    int b, c;
    signed char d[512][512];
};

someFunc() {
    data* someData = new data;

    std::ifstream inFile("inputData.bin", std::ifstream::binary);
    std::ofstream outFile("outputData.bin", std::ofstream::binary);

    // Read from file
    inFile.read(someData, sizeof(data));
    inFile.close();

    // Write to file
    outFile.write(someData, sizeof(data));
    outFile.close();

    delete someData;
}

我还应该提一下,如果你将+ 1 / -1编码为比特,你应该节省大量空间(在我在这里展示的另一个因子为8)。

答案 3 :(得分:0)

对于这些数据,任何自制的东西都不会在高质量的开源二进制存储库中运行。对于此类存储要求,请尝试boost serialize或 - HDF5。我已经在一些具有非常大量doublefloatlongint数据的项目上成功使用了HDF5。发现它很有用,可以控制每个“文件”的压缩率 vs cpu-effort。将数百万个“文件”存储在分层结构的单个“磁盘”文件中也很有用。美国国家航空航天局 - 可能会剥夺我的风格;) - 也使用它。