字符串中的Time.new EINVAL错误,仅限Windows,rb_sysopen



这在Unix上有效,但当我使用Ruby 2.1和2.2将它移到Windows 7(脚本将在其上运行的机器)时,它会失败。

这适用于(Windows):

date = Time.new.localtime.to_s
file = File.new("somefile #{1 + 1}", 'a')
file.close

这不起作用(在Windows上):

date = Time.new.localtime.to_s
file = File.new("somefile #{date}", 'a')
file.close

由此产生的错误是:

test.rb:2:in 'initialize': Invalid argument @ rb_sysopen - somefile 2015-12-07 11:17:52 -0500 (Errno::EINVAL)
          from test.rb:2:in 'new'
          from test.rb:2:in '<main>'

为什么会这样?

时间在这里只是转移注意力。问题是Windows上的文件名中不允许使用冒号(:)。来自MSDN:

使用当前代码页中的任何字符作为名称,包括Unicode字符和扩展字符集中的字符(128–255),以下情况除外:

  • 以下保留字符:
    • <(小于)
    • >(大于)
    • :(结肠)
    • "(双引号)
    • /(正斜杠)
    • (反斜杠)
    • |(立筋或立管)
    • ?(问号)
    • *(星号)
  • 整数值零,有时称为ASCIINUL字符
  • 整数表示形式在1到31之间的字符,但替换数据流中的这些字符除外允许。有关文件流的详细信息,请参见文件流
  • 目标文件系统不允许的任何其他字符

来源:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx

一种解决方案是使用Time#strftime输出一个没有冲突冒号的字符串,例如:

date = Time.new.localtime.strftime("%F %H.%M.%S %z")
file = File.new("somefile #{date}", 'a')
# => #<File:somefile 2015-12-07 11.17.52 -0500>

或者,看看这个SO关于清理用作文件名的字符串主题的回答:如何使Ruby字符串对文件系统安全?

Time.new.localtime查找系统的ENV['TZ']变量,该变量可能未在Windows 7中设置。

您可以按照此链接在Windows上设置CCD_;TZ";系统级的环境变量

来源:http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html#method-i-localtime

最新更新