在我看来,最好的方法是:
headers = CSV.foreach('file.csv').first
请注意,它使用起来非常诱人,CSV.read('file.csv'. headers: true).headers
但问题是,CSV.read
将完整的文件加载到内存中,从而增加了内存占用,而且对于更大的文件使用起来也很慢。请尽可能使用CSV.foreach
. 以下是仅 20 MB 文件的基准测试:
Ruby version: ruby 2.4.1p111
File size: 20M
****************
Time and memory usage with CSV.foreach:
Time: 0.0 seconds
Memory: 0.04 MB
****************
Time and memory usage with CSV.read:
Time: 5.88 seconds
Memory: 314.25 MB
一个 20MB 的文件会增加 314 MB 的内存占用CSV.read
,想象一下 1GB 的文件会对您的系统造成什么影响。简而言之,请不要使用CSV.read
,我使用了,系统崩溃了一个 300MB 的文件。
进一步阅读:如果您想了解更多相关信息,这里有一篇非常好的关于处理大文件的文章。
下面也是我用于基准测试的脚本CSV.foreach
和CSV.read
:
require 'benchmark'
require 'csv'
def print_memory_usage
memory_before = `ps -o rss= -p #{Process.pid}`.to_i
yield
memory_after = `ps -o rss= -p #{Process.pid}`.to_i
puts "Memory: #{((memory_after - memory_before) / 1024.0).round(2)} MB"
end
def print_time_spent
time = Benchmark.realtime do
yield
end
puts "Time: #{time.round(2)} seconds"
end
file_path = '{path_to_csv_file}'
puts 'Ruby version: ' + `ruby -v`
puts 'File size:' + `du -h #{file_path}`
puts 'Time and memory usage with CSV.foreach: '
print_memory_usage do
print_time_spent do
headers = CSV.foreach(file_path, headers: false).first
end
end
puts 'Time and memory usage with CSV.read:'
print_memory_usage do
print_time_spent do
headers = CSV.read(file_path, headers: true).headers
end
end