带有Tempfile的奇怪的Ruby IO

时间:2011-07-13 21:10:41

标签: ruby file-io temporary-files

这让我发疯了。请考虑以下事项:

require 'open-uri'

#set up tempfile
extname = File.extname file_url
basename = File.basename(file_url, extname)
file = Tempfile.new([basename,extname])

#read form URI into tempfile
uri = URI.parse(file_url)
num_bytes_writen = file.write(uri.read)
puts "Wrote #{num_bytes_writen} bytes"

# Reading from my tempfile
puts "Opening: #{file.path} >>"
puts "#### BEGINING OF FILE ####"
puts  File.open(file.path,'rb').read
puts "#### END OF FILE ####"

看起来字节写了,但是当我尝试打开文件时 - 它是空的。怎么了?!

让它变得更奇怪 - 每一个都在Rails控制台中工作,但不是由Resque触发的工作人员执行。

有什么想法吗?谢谢你们

2 个答案:

答案 0 :(得分:16)

这是一个缓冲问题。在尝试读取之前,需要将IO缓冲区刷新到磁盘。 file.close(如果您已完成)或file.flush 之前执行File.open阅读。

更新

我没想过这个,但你不需要重新打开临时文件来阅读它。它已经开放用于编写和阅读,您需要做的就是在阅读之前寻找文件的开头。这样你就不必进行刷新(因为你实际上是从缓冲区读取的)......

# starting partway into your code...
num_bytes_written = file.write(uri.read)
puts "Wrote #{num_bytes_written} bytes"

puts "No need to open #{file.path} >>"
puts "### BEGINNING OF FILE ###"

file.rewind         # set the cursor to the start of the buffer
puts file.read      # cursor is back at the end of the buffer now

puts "### END OF FILE ###"

另一次更新

@carp发表评论后,我调整了上面的代码,使用rewind代替seek 0,因为它还会将lineno重置为0(而不是lineno完成后,如果您使用{{1}}将非常混淆)。实际上它也是一个更具表现力的方法名称。

答案 1 :(得分:1)

始终关闭您的文件。尝试在代码中使用此样式,以避免此类错误:

File.open(myfile,"w") {|f| f.puts content }

这样,当块结束时它会自动调用close。