【问题标题】:Ruby tempfile anomalous behaviorRuby 临时文件异常行为
【发布时间】:2015-08-19 19:56:25
【问题描述】:

这是我的 pry session 输出:

[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 方法不同。

这怎么可能?

【问题讨论】:

  • 您是否更改了epub的内容而不保存文件?
  • 您使用的是什么版本的 Ruby 和 Pry?
  • @SimoneCarletti:在我看来就是这样。但我无法弄清楚到底在哪里。所以,我只是做了 epub.close 和 epub.open,现在我有文件同步了。谢谢大家的解答!

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


【解决方案1】:

魔鬼在细节中。来自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

【讨论】:

  • 是吗?我认为措辞不同......但它们是相同的。
【解决方案2】:

我在 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 创建的临时文件时,我们并不关心或想知道它们的大小。它们是暂时的,会(最终)消失并被视为缓冲区。如果您需要更永久的文件,则创建并写入普通文件。

【讨论】:

    猜你喜欢
    • 2013-08-27
    • 2014-01-20
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    相关资源
    最近更新 更多