调用size方法后,文件只显示为空

时间:2017-02-08 15:56:54

标签: ruby-on-rails ruby file

我在Ruby / Rails中有一个非常奇怪的错误。我使用byebug询问文件包含的内容,但没有显示任何内容。然后我问这个文件有多大,然后当我再次阅读它时,它包含了一些内容。我在Mac OS上。这是输出:

(byebug) File.read(@file)
""
(byebug) @file.size
23
(byebug) File.read(@file)
"HTML + CRT goes here..."

有人有什么想法吗?

我已将其转载为以下Ruby代码:

file = File.new('output.html', 'w')
file.write("Hey")
new = file
puts File.read(new)
puts new.size
puts File.read(new)

2 个答案:

答案 0 :(得分:1)

这是因为你只打开文件进行写作而不是阅读。当你使用

file = File.new('output.html', 'w')

你打开“output.html”进行写作,然后,正如预期的那样你用

写“嘿”
file.write("Hey")

如果你现在打开文件,它将包含“嘿”。

这是奇怪的地方。不需要设置new = file,因为它们是对同一对象的引用。当您使用File.read(new)时,您正在阅读不可读的内容。如果你运行new.read,你会看到这个,因为你会收到错误。当你运行new.size时,它会打开它进行读取,可能会读取它以获得大小。

dupclone它做同样的事情。一旦打开阅读,您就可以正确阅读。

我不知道为什么dupclone打开它进行阅读或为什么当您尝试File.read一个不可读的文件时它会返回"",而当你read它会抛出错误的文件。

这是一个陌生的片段,它重现了你创造的行为:

output = File.new('output.html', 'w')
output.write("Hey")
puts File.read(output) #=> ""
new = output.dup
puts File.read(output) #=> "Hey"

答案 1 :(得分:1)

我认为您与文件的写入和刷新方式有冲突。

写入文件并不能保证在写入sync标志之前立即写入。

  

当sync模式为true时,所有输出立即刷新到底层操作系统,并且不在内部缓冲。

有关详细信息,请参阅syncsync=

如果sync为false,则在中间缓冲区已满或者某些内容触发刷新时(例如关闭文件)将写入文件。自我检查以来已经有一段时间了,但是当写入换行符时可能也会出现。

不要认为设置sync = true是正确的解决方法。我们使用中间缓冲区是一个非常重要的原因:速度。从缓冲区写入/读取更快,然后让操作系统确定何时写入磁盘的正确时间。强制刷新会降低代码速度,如果您经常写入磁盘,可能会降低系统速度。所以要了解它是如何工作的,但除非你理解为什么需要同步,否则不要用它来玩游戏。

当我们open使用Ruby的文件时,我们强烈建议您使用块形式:

File.open('path/to/file', 'w') do |fo|
  ...
end

块形式会自动关闭文件,这会刷新文件,导致文件被写入磁盘。

这不仅限于Ruby,它只是操作系统的工作方式,而且位于其上方的语言继承了这种行为。

另外,我们使用块形式,因为它有助于保留文件句柄。操作系统具有可以一次打开的有限数量的文件。如果你使用非阻止形式,并且一旦你完成它就不愿意关闭文件,并且你处于打开文件的循环中,你最终可能会崩溃你的代码,此时解释器将死亡,所有打开的文件将自动关闭。但是,不要依赖于自动行为,因为它是一个很好的编程实践,可以立即明确关闭,或者使用为我们执行此操作的块形式。