0

I wrote a script that operates on my Mac just fine. It has this line of code in it:

filename = "2011"
  File.open(filename, File::WRONLY|File::CREAT|File::EXCL) do |logfile|
    logfile.puts "MemberID,FirstName,LastName,BadEmail,gender,dateofbirth,ActiveStatus,Phone" 

On Windows the script runs fine and it creates the logfile 2011, but it doesn't actually puts anything to that logfile, so the file is created, the script runs, but the logging doesn't happen.

Does anyone know why? I can't think of what would have changed in the actual functionality of the script that would cause the logging to cease.

4

1 回答 1

1

首先,为了清楚起见,我不会使用标志来指定如何打开/创建文件。我会使用:

File.open(filename, 'a')

这是日志文件的标准模式;如果它不存在,你想创建它,如果它存在,你想追加。

日志记录通常需要在应用程序运行期间多次写入同一个文件。人们喜欢打开日志并让它保持打开状态,但如果代码在文件关闭之前崩溃或者它被 Ruby 或操作系统刷新,则可能会出现问题。此外,Ruby 和操作系统的内置缓冲会导致文件缓冲,然后刷新,当你拖尾文件时,这会使其大块跳跃,如果你是看东西。

您可以通过设置告诉 Ruby 在写入文件时立即强制刷新sync = true

logfile = File.open(filename, 'a')
logfile.sync = true
logfile.puts 'foo'
logfile.close

您可以使用fsync,这也会强制操作系统刷新其缓冲区。

以任何一种方式强制同步的缺点是您否定了缓冲 I/O 的优势。对于普通的文件写入,比如文本文件,不要使用sync,因为你会减慢应用程序的速度。而是让正常的 I/O 像 Ruby 和操作系统想要的那样发生。但是对于记录它是可以接受的,因为记录应该定期发送一行,而不是一大块文本。

您可以立即flush输出,但这会变得多余并违反 DRY 原则:

logfile = File.open(filename, 'a')
logfile.puts 'foo'
logfile.flush
logfile.puts 'bar'
logfile.flush
logfile.close

close在实际关闭文件 I/O 之前刷新。

您可以将日志记录输出包装在一个方法中:

def log(text)
  File.open(log_file, 'a') do |logout|
    logout.puts(text)
  end
end

这将打开,然后关闭日志文件,并自动刷新缓冲区,并且不需要使用sync.

或者,您可以利用 Ruby 的Logger类,让它为您完成所有工作。

于 2013-10-03T20:32:46.777 回答