6

我有一个 10GB 的 CSV 文件,它本质上是一个巨大的方阵。我正在尝试编写一个可以尽可能高效地访问矩阵的单个单元格的函数,即矩阵[12345,20000]。

鉴于它的大小,显然不可能将整个矩阵加载到二维数组中,我需要以某种方式直接从文件中读取值。

我已经用 Google 搜索了使用 FileStream.Seek 查看文件随机访问,但不幸的是,由于可变舍入每个单元格不是固定宽度。我不可能通过某种算术寻找特定字节并知道我正在查看的单元格。

我考虑扫描文件并为每行的第一个字节的索引创建一个查找表。这样,如果我想访问 matrix[12345,20000] 我会寻找第 12345 行的开头,然后扫描整个行,计算逗号,直到我到达正确的单元格。

我正要尝试这个,但还有其他人有更好的想法吗?我敢肯定我不会是第一个尝试处理这样的文件的人。

干杯

编辑:我应该注意到该文件包含一个非常稀疏的矩阵。如果解析 CSV 文件最终太慢,我会考虑将文件转换为更合适且更易于处理的文件格式。存储稀疏矩阵的最佳方法是什么?

4

6 回答 6

3

我已经将 Lumenworks CSV 阅读器用于相当大的 CSV 文件,可能值得快速查看一下它解析文件的速度。

Lumenworks CSV

于 2011-01-27T23:50:39.290 回答
3

首先,您希望如何引用特定行?它是行的索引,以便您有另一个表或可以帮助您知道您感兴趣的行的东西吗?还是通过 id 或其他什么?

这些想法浮现在脑海

  • 你的方法
  • 二进制搜索。假设您有平均长度(大小/行),您可以使用二进制搜索来查找行,假设行中有一个有序的标识符,并且可以告诉您是否被击中或错过。
  • 将其加载到数据库中!顺便说一句,是什么阻止你这样做?您甚至可以使用免费的 SQL express ,并且为了绕过大小限制,您可以将数据分片到多个数据库。
于 2011-01-27T23:56:10.727 回答
1

索引文件将是你能做的最好的。我打赌。由于行的大小未知,除了扫描文件或拥有索引之外,没有办法直接跳到该行。

唯一的问题是您的索引有多大。如果它太大,您可以通过仅每 5 行(例如)索引一次并在 5 行范围内扫描来缩小它。

于 2011-01-27T23:54:05.860 回答
0

我不同意您不应该将文件加载到 RAM 中,特别是如果您使用 64 位操作系统。

分配大小为 12345x20000 的矩阵应该不是问题:双精度大约只有 1.9 GB。事实上,即使大小更大,我仍然会在 64 位平台下推荐这种方法(参见“虚拟内存”)。

其次,您说您的矩阵是稀疏的,因此您可以加载到 RAM 中,但使用稀疏表示来节省一些内存。

总之,如果您的应用程序需要多次访问您的矩阵并且性能有些重要,那么将其放入 RAM 绝对是我最喜欢的方法。

于 2011-01-28T00:52:56.530 回答
0

预处理文件,使字段宽度固定。然后,您可以轻松地进行随机阅读。

从过去做类似的事情,您应该能够编写一些简单的代码,从本地磁盘读取 10G 可变宽度文件,并在几分钟(~20)分钟内将 10G 固定宽度文件写入本地磁盘。如果前期投资得到回报,取决于您需要进行多少随机读取以及要读取的文件多久更改一次。

于 2011-01-28T00:56:03.953 回答
0

如果您创建了 12345 个使用延迟实例化读取的单独文件怎么办。只有在需要数据时才会读取每个文件。如果数据完全稀疏,您可以使用 IsEmpty bool 属性创建数据结构。

您是否需要一遍又一遍地访问同一个元素,还是只需要读取每个元素一次?

于 2011-01-28T04:29:03.760 回答