Ruby on rails 调用size方法后,仅不显示为空的文件
我在Ruby/Rails中有一个非常奇怪的bug。我使用byebug询问文件包含什么,但没有显示任何内容。然后我问这个文件有多大,然后当我再次阅读它时,它包含了一些东西。我使用Mac OS。以下是输出:Ruby on rails 调用size方法后,仅不显示为空的文件,ruby-on-rails,ruby,file,Ruby On Rails,Ruby,File,我在Ruby/Rails中有一个非常奇怪的bug。我使用byebug询问文件包含什么,但没有显示任何内容。然后我问这个文件有多大,然后当我再次阅读它时,它包含了一些东西。我使用Mac OS。以下是输出: (byebug) File.read(@file) "" (byebug) @file.size 23 (byebug) File.read(@file) "HTML + CRT goes here..." 有人有什么想法吗 我已将其复制到以下Ruby代码中: file = File.new(
(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)
这是因为您只打开文件进行写入,而不是读取。当你使用
file = File.new('output.html', 'w')
您打开“output.html”进行编写,然后,正如预期的那样,使用
file.write("Hey")
如果现在打开该文件,它将包含“嘿”
这就是它变得奇怪的地方。不需要设置new=file
,因为它们是对同一对象的引用。当您使用File.read(new)
时,您正在读取一些不可读的内容。如果您运行new.read
,您将看到这一点,因为您将得到一个错误。当您运行new.size
时,它会打开它进行读取,可能是为了读取它以获得大小
dup
ing它和clone
ing它做同样的事情。一旦打开阅读,您就可以正确阅读
我不知道的是,为什么dup
或clone
会打开它进行读取,或者为什么当您尝试文件时,读取一个不可读的文件会返回”
,而当您读取文件时会抛出错误
下面是一个非常奇怪的片段,它再现了您创建的行为:
output = File.new('output.html', 'w')
output.write("Hey")
puts File.read(output) #=> ""
new = output.dup
puts File.read(output) #=> "Hey"
这是因为您只打开文件进行写入,而不是读取。当你使用
file = File.new('output.html', 'w')
您打开“output.html”进行编写,然后,正如预期的那样,使用
file.write("Hey")
如果现在打开该文件,它将包含“嘿”
这就是它变得奇怪的地方。不需要设置new=file
,因为它们是对同一对象的引用。当您使用File.read(new)
时,您正在读取一些不可读的内容。如果您运行new.read
,您将看到这一点,因为您将得到一个错误。当您运行new.size
时,它会打开它进行读取,可能是为了读取它以获得大小
dup
ing它和clone
ing它做同样的事情。一旦打开阅读,您就可以正确阅读
我不知道的是,为什么dup
或clone
会打开它进行读取,或者为什么当您尝试文件时,读取一个不可读的文件会返回”
,而当您读取文件时会抛出错误
下面是一个非常奇怪的片段,它再现了您创建的行为:
output = File.new('output.html', 'w')
output.write("Hey")
puts File.read(output) #=> ""
new = output.dup
puts File.read(output) #=> "Hey"
我认为您正在与文件写入和刷新到磁盘的方式发生冲突
除非设置了sync
标志,否则写入文件并不保证立即写入
当sync mode为true时,所有输出将立即刷新到底层操作系统,并且不会在内部进行缓冲
有关更多信息,请参阅和
如果sync
为false,则会在中间缓冲区已满时写入文件,或者如果有什么触发刷新,例如关闭文件。我已经有一段时间没有检查过了,但在写新行时也可能会出现这种情况
不要认为设置sync=true
是正确的解决方法。我们使用中间缓冲区有一个非常重要的原因:速度。从缓冲区进行写/读操作,然后让操作系统确定何时是写入磁盘的正确时间,这会快得多。强制刷新会降低代码的速度,如果您大量写入磁盘,则会降低系统的速度。所以,请理解它是如何工作的,但除非您理解为什么需要同步,否则不要使用它玩游戏
当我们使用Ruby打开文件时,强烈建议我们使用块形式:
File.open('path/to/file', 'w') do |fo|
...
end
块窗体自动关闭文件,这将刷新文件,导致文件写入磁盘
这种情况并不局限于Ruby,而是操作系统的工作方式,它上面的语言继承了这种行为
此外,我们使用块形式,因为它有助于保留文件句柄。操作系统一次可以打开的文件数量有限。如果您使用非块形式,并且在完成文件后不努力关闭文件,并且处于打开文件的循环中,则最终可能导致代码崩溃,此时解释器将死亡,所有打开的文件将自动关闭。但不要依赖于自动行为,因为立即显式关闭或使用为我们执行此操作的块形式是很好的编程实践。我认为您正在与文件写入和刷新到磁盘的方式发生冲突
除非设置了sync
标志,否则写入文件并不保证立即写入
当sync mode为true时,所有输出将立即刷新到底层操作系统,并且不会在内部进行缓冲
有关更多信息,请参阅和
如果sync
为false,则会在中间缓冲区已满时写入文件,或者如果有什么触发刷新,例如关闭文件。我已经有一段时间没有检查过了,但在写新行时也可能会出现这种情况
不要认为设置sync=true
是正确的解决方法。我们使用中间缓冲区有一个非常重要的原因:速度。从缓冲区进行写/读操作,然后让操作系统确定何时是写入磁盘的正确时间,这会快得多。强制刷新会降低代码的速度,如果您大量写入磁盘,则会降低系统的速度。所以,请理解它是如何工作的,但除非您理解为什么需要同步,否则不要使用它玩游戏
当我们使用Ruby打开文件时,强烈建议我们使用块形式:
File.open('path/to/file', 'w') do |fo|
...
end
块窗体自动关闭文件,这将刷新它,导致文件丢失