Ruby tempfile异常行为

时间:2015-08-19 19:56:25

标签: ruby-on-rails ruby file temporary-files pry

这是我的pry会话输出:

[1] pry(SomeTask)> epub
=> #<File:/somepath/tmp/x.epub>
[2] pry(SomeTask)> epub.size
=> 134
[3] pry(SomeTask)> File.size("/somepath/tmp/x.epub")
=> 44299
[4] pry(SomeTask)> epub.class
=> Tempfile

我看到File.size产生的结果与Tempfile实例的size方法不同。

这怎么可能?

2 个答案:

答案 0 :(得分:3)

魔鬼在于细节。来自Tempfile#size的文件(强调我的):

  

<强>尺寸()

     

返回临时文件的大小。 作为副作用,在确定大小之前刷新IO缓冲区。

发生的事情是你在刷新缓冲区之前使用File.size来读取文件的大小 - 即。在所有字节都写入文件之前 - 然后你使用Tempfile#size,它会在计算大小之前刷新缓冲区:

tmp = Tempfile.new('foo')
tmp.write('a' * 1000)
File.size(tmp)
# => 0
tmp.size
# => 1000

但是看看在 tmp.size之前致电File.size(tmp) 时会发生什么:

tmp = Tempfile.new('bar')
tmp.write('a' * 1000)
tmp.size
# => 1000
File.size(tmp)
# => 1000

您可以通过手动刷新缓冲区来获取File.size之外的行为:

tmp = Tempfile.new('baz')
tmp.write('a' * 1000)
tmp.flush
File.size(tmp)
# => 1000

答案 1 :(得分:0)

我在Ruby 2.2.2上使用Pry版本0.10.1并且不能复制这种情况:

[1] (pry) main: 0> foo = Tempfile.new('foo')
#<File:/var/folders/yb/whn8dwns6rl92jswry5cz87dsgk2n1/T/foo20150819-83612-1tpkqm4>
[2] (pry) main: 0> File.size(foo.path)
=> 0
[3] (pry) main: 0> foo.size
=> 0

初始化后,文件大小为0字节。

[4] (pry) main: 0> foo.write('a')
=> 1
[5] (pry) main: 0> File.size(foo.path)
=> 0

将一个字符写入foo后,数据已被缓冲,而不是像我期望的那样刷新到磁盘。

[6] (pry) main: 0> foo.size
=> 1
[7] (pry) main: 0> File.size(foo.path)
=> 1

foo.size刷新缓冲区然后返回文件的大小,该大小与File.size所说的匹配。

在处理Tempfile创建的临时文件时,我们不关心或想知道它们的大小。它们是暂时的并且会消失(最终)并被视为缓冲区。如果您需要一个更永久的文件,那么创建并写入普通文件。