我在S3上存储了两个CSV文件。当我open
其中一个时,会返回File
。当我open
另一个时,会返回StringIO
。
fn1 #=> "http://SOMEWHERE.s3.amazonaws.com/setup_data/d1/file1.csv"
open(fn1) #=> #<File:/var/folders/sm/k7kyd0ns4k9bhfy7yqpjl2mh0000gn/T/open-uri20140814-26070-11cyjn1>
fn2 #=> "http://SOMEWHERE.s3.amazonaws.com/setup_data/d2/d3/file2.csv"
open(fn2) #=> #<StringIO:0x007f9718670ff0>
为什么呢?有没有办法用一致的数据类型打开它们?
我需要将相同的数据类型String
传递给CSV.read(open(file_url))
,如果有时它会获得File
,有时会{{1} }}
它们是通过不同的ruby脚本创建的(它们包含非常不同的数据)。
在我的Mac上,它们似乎都是普通的文本CSV文件,它们通过AWS控制台上传,并具有相同的权限和相同的元数据(内容类型:application / octet-stream)。
答案 0 :(得分:7)
这是设计的。如果对象的大小大于10240字节,则创建临时文件。来自source:
StringMax = 10240
def <<(str)
@io << str
@size += str.length
if StringIO === @io && StringMax < @size
require 'tempfile'
io = Tempfile.new('open-uri')
io.binmode
Meta.init io, @io if Meta === @io
io << @io.string
@io = io
end
end
如果您需要StringIO
个对象,可以使用fastercsv
。
答案 1 :(得分:1)
CSV::read
期望文件路径作为其参数,而不是已打开的IO对象。然后它将打开文件并读取内容。您的代码适用于Tempfile案例,因为Ruby会在传递给to_path
的任何内容后面调用File::open
,并且File
会响应此方法。会发生什么情况是CSV在同一文件上打开另一个 IO。
您可以创建一个新的CSV对象并在其上调用CSV::read
(实例方法,而不是类方法),而不是使用read
。 CSV:new
正确处理IO对象:
CSV.new(open(file_url)).read