使用 Javascript 读取大型 CSV 文件而不将所有内容加载到内存的最佳方法
Best way to read from a big CSV file without loading everything to memory using Javascript
我正在使用 Atom/Electron 构建一个基于数据的视频可视化应用。每个视频都有一个对应的 CSV 文件,其中包含每一帧的信息。视频大约100分钟,所以文件有很多数据!
我遇到的问题是加载和解析文件需要几秒钟的时间。大多数时候这不是问题。但是我需要制作部分视频的播放列表,每次更改视频时加载整个 CSV 文件不是一个可行的选择。
我一直在寻找文件流选项作为 fast-csv,但我没有设法开始读取文件的任意部分。
编辑:来自 FS 文档。在这种情况下,问题是我如何知道文件中哪个字节对应于我想要的位置?
options can include start and end values to read a range of bytes
from the file instead of the entire file. Both start and end are
inclusive and start at 0.
对于这种情况,您认为哪种方法更好、性能最好?
具体来说:
有没有办法从 CSV 文件的任何部分开始读取流?
你认为有另一种存储方法可以让我更好地解决这个问题吗?
更新:
最后,我通过将数据以二进制格式存储在文件中解决了这个问题。因为我知道文件有多少列,所以我可以直接从文件段中读取而不会影响性能。
为此,我强烈推荐 Papaparse。它允许流式传输 CSV 'row-by-row',可以根据文件中的 headers 以 JSON 格式进行处理。
在传递给解析函数的配置 object 中,您可以提供一个 'step' 参数,该参数是文件逐行执行时要为文件的每一行执行的函数。
注意:也可以配置为使用 worker-thread 以在处理非常大的 CSV 文件时提高性能
根据我的评论,Sqlite 似乎是您要找的东西。从长远来看,它可能不是您的永久解决方案 运行,但在您决定是坚持使用它还是编写自己的解决方案时,它肯定会暂时起作用。
Sqlite 的内部工作原理
Sqlite 针对核心进行了优化,但它具有三个主要特性,使其执行速度比普通磁盘读取更快,尤其是 CSV 文件:
- 整个数据库(您创建的每个数据库)都存储在 1 个文件中,而不是多个文件或记录中。
- 此文件被分页为 1024 字节 (1K) 块,使您可以轻松地在数据中跳转。
- (实际上是 2 的一部分)整个数据库和分页系统是一个巨大的二叉树,通常需要不到 10 次跳转才能找到任何给定数据。所以通俗的说就是极快!
如果您真的有兴趣了解所有这些的全部范围,我发现没有比 this amazing blog post by Julia Evans 更好的解释了。
可能的缺点
除了内部工作之外,Sqlite 被设计为在用户机器上工作的客户端。如果这不是一个可行的解决方案,则可以采取一些变通办法。例如,Sqlite 可以用作 Web 服务器,但它在独立安装或混合安装中表现最佳。还要记住每个客户端计算机都是不同的。一台计算机处理记录的速度可能比另一台计算机快,但通常您不必担心,因为客户端计算机通常负载很小。
- 独立需要一切都在客户端。这通常是 Sqlite 的使用方式。我过去曾将它用于游戏,利用 sqlite4java's API 通过 Java 连接到数据库; API 使整个体验感觉就像服务器上的 PHP 和 MySQL。您可能需要查找其他 API,因为 Sqlite 是用 C 语言编写的。
- 混合灌输的完成方式与独立灌输相同,但您在程序中编写 link 到实际服务器。对于我帮助制作的游戏,我们会跟踪分数和用户数据等内容,然后在可以连接的情况下定期在后台将其传递给实际服务器。这也适用于相反的情况。您可以启动用户,但首先 运行 它可以下载您需要的所有内容,从那时起,它就会与服务器上的内容保持同步。
总结
Sqlite 可以满足您的需要,但可能需要一些功课才能按照您需要的方式进行设置。例如,Sqlite4java 易于安装,但由于其文档太少而难以学习;不过,Stack Overflow 让我度过了难关。 Sqlite 也是一种使用它而忘记它的安装类型所以回答你的问题,它会像蛋糕一样每秒处理 25 行,你不需要担心只优化你自己的代码。
我正在使用 Atom/Electron 构建一个基于数据的视频可视化应用。每个视频都有一个对应的 CSV 文件,其中包含每一帧的信息。视频大约100分钟,所以文件有很多数据!
我遇到的问题是加载和解析文件需要几秒钟的时间。大多数时候这不是问题。但是我需要制作部分视频的播放列表,每次更改视频时加载整个 CSV 文件不是一个可行的选择。
我一直在寻找文件流选项作为 fast-csv,但我没有设法开始读取文件的任意部分。
编辑:来自 FS 文档。在这种情况下,问题是我如何知道文件中哪个字节对应于我想要的位置?
options can include start and end values to read a range of bytes from the file instead of the entire file. Both start and end are inclusive and start at 0.
对于这种情况,您认为哪种方法更好、性能最好?
具体来说:
有没有办法从 CSV 文件的任何部分开始读取流?
你认为有另一种存储方法可以让我更好地解决这个问题吗?
更新:
最后,我通过将数据以二进制格式存储在文件中解决了这个问题。因为我知道文件有多少列,所以我可以直接从文件段中读取而不会影响性能。
为此,我强烈推荐 Papaparse。它允许流式传输 CSV 'row-by-row',可以根据文件中的 headers 以 JSON 格式进行处理。
在传递给解析函数的配置 object 中,您可以提供一个 'step' 参数,该参数是文件逐行执行时要为文件的每一行执行的函数。
注意:也可以配置为使用 worker-thread 以在处理非常大的 CSV 文件时提高性能
根据我的评论,Sqlite 似乎是您要找的东西。从长远来看,它可能不是您的永久解决方案 运行,但在您决定是坚持使用它还是编写自己的解决方案时,它肯定会暂时起作用。
Sqlite 的内部工作原理
Sqlite 针对核心进行了优化,但它具有三个主要特性,使其执行速度比普通磁盘读取更快,尤其是 CSV 文件:
- 整个数据库(您创建的每个数据库)都存储在 1 个文件中,而不是多个文件或记录中。
- 此文件被分页为 1024 字节 (1K) 块,使您可以轻松地在数据中跳转。
- (实际上是 2 的一部分)整个数据库和分页系统是一个巨大的二叉树,通常需要不到 10 次跳转才能找到任何给定数据。所以通俗的说就是极快!
如果您真的有兴趣了解所有这些的全部范围,我发现没有比 this amazing blog post by Julia Evans 更好的解释了。
可能的缺点
除了内部工作之外,Sqlite 被设计为在用户机器上工作的客户端。如果这不是一个可行的解决方案,则可以采取一些变通办法。例如,Sqlite 可以用作 Web 服务器,但它在独立安装或混合安装中表现最佳。还要记住每个客户端计算机都是不同的。一台计算机处理记录的速度可能比另一台计算机快,但通常您不必担心,因为客户端计算机通常负载很小。
- 独立需要一切都在客户端。这通常是 Sqlite 的使用方式。我过去曾将它用于游戏,利用 sqlite4java's API 通过 Java 连接到数据库; API 使整个体验感觉就像服务器上的 PHP 和 MySQL。您可能需要查找其他 API,因为 Sqlite 是用 C 语言编写的。
- 混合灌输的完成方式与独立灌输相同,但您在程序中编写 link 到实际服务器。对于我帮助制作的游戏,我们会跟踪分数和用户数据等内容,然后在可以连接的情况下定期在后台将其传递给实际服务器。这也适用于相反的情况。您可以启动用户,但首先 运行 它可以下载您需要的所有内容,从那时起,它就会与服务器上的内容保持同步。
总结
Sqlite 可以满足您的需要,但可能需要一些功课才能按照您需要的方式进行设置。例如,Sqlite4java 易于安装,但由于其文档太少而难以学习;不过,Stack Overflow 让我度过了难关。 Sqlite 也是一种使用它而忘记它的安装类型所以回答你的问题,它会像蛋糕一样每秒处理 25 行,你不需要担心只优化你自己的代码。