6

我在服务器上有一个大的 CSV 文件,我想分块下载和处理,而不是将整个文件读入内存。经过一番摸索后,我想出了这个:

require open-uri

open("http://example.com/#{LARGE_CSV_FILE}") do |file|
  file.each_slice(50_000) do |fifty_thousand_lines|
    MyModel.import fifty_thousand_lines.join
  end
end

我的理解是open-uri's#open将包装 HTTP GET 并返回一个IO-like 可枚举对象。#each_slice(n)将一次将 n 行的数组传递给块。然后我加入并处理这些行。

这个导入很好,看着我的 OS X iStat 菜单,看起来 ruby​​ 进程的内存使用并没有失控。但是,看起来我一次下载了所有文件。如果没有内存使用爆炸,这怎么可能?

ruby 是否将其下载到临时文件中,然后逐行从磁盘中读取?我原以为open-uri会改为限制 HTTP 连接,并且仅在其块完成处理其一批数据时才下载更多数据。

这是下载和处理文件而不将其全部加载到内存中的正确方法吗?

4

1 回答 1

1

是的,它确实下载到临时文件。这很容易从控制台观察到:

2.0.0-p247 :001 > require 'open-uri'
 => true
2.0.0-p247 :002 > f = open("http://stackoverflow.com/questions/19279715/does-ruby-open-uri-http-streaming-throttle-the-download-or-save-to-a-temp-file")
 => #<Tempfile:/tmp/open-uri20140220-27172-1kcjwk2>
于 2014-02-21T04:16:24.983 回答