新手问题 Ruby 中读取大文件

thxagain · 2016年11月09日 · 最后由 thxagain 回复于 2016年12月05日 · 3575 次阅读

类似File.open背后具体做了什么事情呢?

我很好奇假设一个文件有 2G 大,那么会把它一次性读入内存中么?

类似这样写是否就可以做到只读取指定行号的文件内容了:

file = File.open(log_file)
log_file = logcat_filter(file, @filter_level, @filter_tag)

def log_file_content(log_file, start_line, end_line)
  log_file_content = []
  index = 0
  log_file.each do |line|
    index += 1
    # 只读取start_line到end_line的数据
    next if !start_line.blank? && index < start_line.to_i
    break if !end_line.blank? && index >= end_line.to_i

    log_file_content << line unless line.blank?
  end
  log_file_content
end

#1 楼 @easonlovewan 这个是说 CSV 的,感觉文件越大,似乎确实内存会出问题。

我刚翻到一篇博客说这个事情的,是使用 Enumerator 的lazy方法来避免。

较早一篇文章,说 ruby 读写 IO 占用内存和时间问题的:https://ruby-china.org/topics/31444

#3 楼 @flemon1986

我注意到这篇文章中前面几个方法都是File.read,最后一个占用内存小的是使用了File.open,似乎这里会有影响。

什么影响?

#5 楼 @flemon1986 似乎File.readFile.open两种不同的读取方式,会影响占用的内存不同

是的,两种打开方式不一样 read 是读数据,文件大,内存~=文件大小 open 是 new, new 加 block 就是打开一个新文件 (新 IO stream),对其逐行插入内容,内存~=行大小 (最大那行)

如果要提取数据量大的话,直接全部读入然后扫描换行符位置然后提取可能更快,毕竟相当于全部缓存或者按行缓存和拼接。时间空间平衡度是不一样的。

如果你前面的行不删掉,内存不删掉,那还不如全部一次性读出来...

mmap 的读取方式其实效率更高,把文件做内存映射,然后操作系统去优化,如果没必要就不会全部读进内存里

@Artoria 请问 File.open 的方式是全部读入么?

@luikore

我理解你的意思是如果前面的行不删掉,内存不删掉,那还是会占用着内存的,直到被 GC 回收?

那 Ruby 中读取文件的方式是 mmap 么?是不是意味着,无论多大的文件,全部读入内存就好...会不会把内存撑爆😰

需要 登录 后方可回复, 如果你还没有账号请 注册新账号