如何将一个巨大的文件加载到Racket中的String或列表中?

时间:2017-02-03 16:20:22

标签: list functional-programming scheme racket

我有一个需要进行操作的巨大文件。巨大的约五十万字。

我只想把它读成一个列表或字符串,这样我以后就可以用它做了。

我也知道我可以使用file->字符串将其加载到字符串中或使用file-> list,file->行,但这些似乎需要花费太长时间。

这是将它加载到列表中的正确方法吗?:

(define my-list (with-input-from-file "myFile.txt" read))

每当我运行程序时,我都会打印出第一行。似乎适用于较小的文件。

2 个答案:

答案 0 :(得分:0)

我假设有50万字,你的意思是你的文件大约是5 GB。

如果是这种情况,你真的不想把整个事情都读到内存中。我的意思是,当然,整个事情在技术上都适合许多计算机拥有的RAM(虽然肯定不是全部),但它也需要一段时间才能完成。使用SSD这将需要大约10秒,这是可以的,我猜,根据您的应用程序,它可能100%罚款,但它对于标准桌面应用程序肯定不是很快。但是,如果您从硬盘读取它,它将花费60秒。而且假设您的硬盘没有对文件进行分段,如果是这样,它会更慢。

这两种情况都是理想的最小值,实际上将5 GB文件完全加载到RAM中的速度最慢。 (虽然在一些非常罕见的情况下,这是你想要的,通常在你做高性能计算时。)

正如@Carcigenicate建议的那样,更好的想法是将文件懒惰地传输到你的程序中,这样你就不需要长时间停顿了。为此,我建议使用in-input-port-bytesin-bytes-lines。这两个都会生成流,然后您可以使用它们来处理数据,第一个流一次为您提供一个字节,另一个为您提供一行字节。直到你达到EOF。您可以在for

中执行此操作
(call-with-input-file "file.txt"
  (lambda (f)
    (for/fold ([counter 0])
              ([i (in-input-port-bytes f)])
      (+ counter 1))

以上示例是计算文件中字节数的慢速方法。但它显示了如何使用in-input-port-bytes

还有其他功能可以创建字符流而不是文件中的字节:in-linesread-port等。

答案 1 :(得分:0)

我强烈认为你的问题不是中读取字符串,而是将其打印出来

具体来说,读取这个大小的文件似乎需要大约0.03秒。

我使用这个程序生成了一个文件:

#lang racket

(define a (time (file->string "/tmp/foo.txt")))

然后,我这样读了:

cpu time: 30 real time: 30 gc time: 17

...并产生了这个输出:

file->string

....表示30毫秒。

请注意,因为我将define包裹在@media print{ body * { visibility: hidden; } #page, #page * { visibility: visible; } #page { position: absolute; top: 0; left: 0; } } 中,所以我将整个内容打印出来。这需要很长时间。