【问题标题】:Run Time Critical, reading operation of CSV files in CRun Time Critical,C 中 CSV 文件的读取操作
【发布时间】:2011-02-09 11:22:27
【问题描述】:

有没有办法编写一个快速、有效的读取 csv 文件的方法?[这里要注意的一点是:我说的是一个超过 100 万行的 csv 文件]

运行时间是这里的关键指标。

互联网上的一个资源专注于使用二进制文件操作来批量读取。但我敢肯定,如果它有助于阅读 CSV 文件

还有其他方法,例如 Robert Gamble 编写的 SourceForge 代码。有没有办法用原生函数来写?

编辑:让我们以更清晰、更好的方式拆分整个问题:

  1. 是否有一种有效的(运行时关键的)方法来读取 C 中的文件? (在本例中为一百万行长的 .csv 文件)

  2. 有没有一种快速有效的方法来解析 csv 文件?

【问题讨论】:

  • 重要的是可以使用Assembly来提高性能吗???

标签: c file csv


【解决方案1】:

没有一种方法可以一直最快地读取和解析任何类型的文件。但是,您可能希望为 CSV 构建 Ragel 语法;那些往往很快。您可以将其调整为您特定类型的 CSV(逗号分隔、;-分隔、仅数字等),并且可能跳过您不会使用的任何数据。我在使用可以跳过大部分输入(数据库转储)的特定于数据集的 SQL 解析器方面有很好的经验。

批量读取可能是个好主意,但您应该根据实际数据衡量它是否真的比stdio-buffering 快。在 Windows 上使用二进制 I/O 可能会加快速度,但您需要在其他地方处理换行符。

【讨论】:

  • Ragel 看起来很有趣。我认为我不能在这个特定时间使用它(因为代码将在我的机器以外的机器上运行,因此可能需要安装 ragel)。我还没有给 ragel 一个完整的 dekko,但它看起来确实很有趣。还有其他方法可以达到同样的效果吗?
  • @Soham:你只需要在开发机器上安装Ragel即可。它编译为 C 代码而没有进一步的依赖关系。 Lex/Yacc 提供相同的功能。
【解决方案2】:

根据我的经验,CSV 文件的解析——即使是高级解释语言——通常也不是瓶颈。通常大量数据占用大量空间; CSV 文件很大,大部分加载时间是 I/O,即 硬盘 将大量数字读入内存。

所以我的强烈建议是考虑压缩 CSV。 gzip 的工作效率很高,它可以即时压缩和恢复 CSV 流,通过大大减少文件大小和 I/O 时间来加快保存和加载速度。

如果您在 Unix 下进行开发,您可以尝试这样做,无需额外代码,受益于通过 gzip -cgunzip -c 管道化 CSV 输入和输出。试试吧——对我来说,它加速了数十次。

【讨论】:

  • 是的,我想,我的问题是错误的。解析不像 I/O 那样大的瓶颈。是否有一些示例代码如何使用 gzip 来实现更快的 i/o?
  • 从一个假设的test.c 开始,它输出巨大的 CSV,您可以将其编译为test 并测量压缩和不压缩的速度:time test | gzip -c > test.csv.gztime test > test.csv。如果您不使用 Unix,则必须搜索并合并一些 gzip 处理代码。
【解决方案3】:

使用setvbuf 将输入缓冲区设置为比默认值大得多的大小。这是您可以在 C 语言中提高读取速度的唯一方法。还要做一些时间测试,因为会有一个收益递减点,超过这个点就没有增加缓冲区大小的意义了。

在 C 之外,您可以先将该 .CSV 文件放到 SSD 驱动器上,或者将其存储在压缩文件系统上。

【讨论】:

    【解决方案4】:

    最好的办法是将大块文本拖入内存(或“内存映射”文件),并在内存中处理文本。

    效率的难点在于文本行是可变长度的记录。通常,会读取文本直到找到 行尾 终止符。一般来说,这意味着读取一个字符,并检查 eol。许多平台和库尝试通过读取数据块并在数据中搜索 eol 来提高效率。

    您的 CSV 格式使问题进一步复杂化。在 CSV 文件中,字段 是可变长度记录。同样,搜索终端字符,例如逗号、制表符或竖线。

    如果您想要更好的性能,您必须将数据布局更改为固定字段长度和固定记录长度。如有必要,填充字段。应用程序可以删除额外的填充。就阅读而言,固定长度记录非常有效。只需读取 N 个字节数。没有扫描,只是转储到某处的缓冲区中。

    固定长度字段允许随机访问记录(或文本行)。字段的索引是恒定的,可以很容易地计算出来。无需搜索。

    总之,可变长度记录和字段就其本质而言,并不是最有效的数据结构。时间浪费在寻找终端字符上。固定长度记录和固定长度字段更有效,因为它们不需要搜索。

    如果您的应用程序是数据密集型的,那么重组数据可能会使程序更高效。

    【讨论】:

    • 我没有提到构图,因为我没有意识到它可能很重要,但为了清楚起见,我们假设它是 1000 万行 x 6 列的双精度数。这样,是否可以假设线长是统一的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 2012-08-18
    • 2018-01-20
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多