高效地将浮点数导出到 CSV 文件

Efficiently exporting floating-point numbers to a CSV file

出于预计算目的,我需要在逗号分隔文件中存储大量(数千万)单精度浮点数。

我的性能优先顺序是:

  1. 阅读速度
  2. 文件大小
  3. 写入速度

现在我只是在写数字的字符串表示,这显然可以改进。有什么好的方法可以做到这一点?

最快和最有效的解决方案(文件大小)是以二进制格式存储二进制数据。在粗略的线条(没有以任何方式优化):

private static IEnumerable<float> read()
{
    using (var file = new FileStream(//whatever)
    using (var reader = new BinaryReader(file))
    {
        while (file.Position < file.Length)
            yield return reader.ReadSingle();
    }
}

private static void write(IEnumerable<float> ff)
{
    using (var file = new FileStream(//whatever)
    using (var writer = new BinaryWriter(file))
    {
        foreach (var f in ff)
            writer.Write(f);
    }
}

如果您需要保留 csv 格式,那么在写入和读取浮点数的文本表示方面确实没有任何选项,这会使处理速度相当慢,并且文件大小可能会大几个数量级。

对于你的#2 objective,你需要知道你的数字的哪些部分真正重要,以及是否存在相关性。它们的范围受限吗?它们的测量精度是多少?所有六位数都重要吗?这是一个连续数字之间差异很小的时间序列吗?

该信息可用于压缩浮点值序列。限制它们值所代表的范围和精度。如果存在相关性,您可以获取连续值之间的差异并仅发送那些值(第一个除外)。或者你可以有一个更复杂的模型来预测下一个数字,给定它前面的序列,并发送每个数字的实际值和预测值之间的差异。

然后您可以尝试使用标准无损压缩器压缩结果,例如 gzip、zlib、zstd、lz4 等

这一切都会产生一个紧凑的二进制文件。如果您真的需要结果是可读的 .csv,您仍然可以限制精度并进行差异编码,以提供一些压缩。然后需要在另一端撤消差异编码。