即时读取压缩的csv文件

时间:2014-05-04 03:18:19

标签: ruby csv bzip2

我已经编写了一些csv文件并使用以下代码对其进行压缩:

arr = (0...2**16).to_a
File.open('file.bz2', 'wb') do |f|
  writer = Bzip2::Writer.new f
  CSV(writer) do |csv|
    (2**16).times { csv << arr }
  end
  writer.close
end

我想阅读此csv bzip2ed 文件(使用bzip2压缩的csv文件)。这些未压缩的文件看起来像:

1,2
4,12
5,2
8,7
1,3
...

所以我尝试了这段代码:

Bzip2::Reader.open(filename) do |bzip2|
  CSV.foreach(bzip2) do |row|
    puts row.inspect
  end
end

但是当它被执行时,它会抛出:

/Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1256:in `initialize': no implicit conversion of Bzip2::Reader into String (TypeError)
from /Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1256:in `open'
from /Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1256:in `open'
from /Users/foo/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/csv.rb:1121:in `foreach'
from worm_pathfinder_solver.rb:79:in `block in <main>'
from worm_pathfinder_solver.rb:77:in `open'
from worm_pathfinder_solver.rb:77:in `<main>'

问题

有什么问题? 我该怎么办?

3 个答案:

答案 0 :(得分:10)

CSV.foreach假设您正在传递文件路径以进行打开。如果要将流传递给CSV,则需要更明确并使用CSV.new。此代码将处理gzip压缩文件:

Zlib::GzipReader.open(filename) do |gzip|
  csv = CSV.new(gzip)
  csv.each do |row|
    puts row.inspect
  end
end

答案 1 :(得分:2)

根据简要文档,您可能需要在bzip2对象上发送read方法(未经测试):

Bzip2::Reader.open(filename) do |bzip2|
  CSV.foreach(bzip2.read) do |row|
    #               ^^^^
    puts row.inspect
  end
end

答案 2 :(得分:1)

我的猜测是CSV尝试将Bzip2::Reader转换为字符串,但不知道如何并简单地抛出异常。您可以手动将数据读入字符串,然后将其传递给CSV

虽然它很奇怪,因为它可以处理Bzip2 :: Writer就好了。