身陷囹圄
2009-08-20 13:39
浏览 248

windows下ruby1.9.1编码问题

[code="ruby"]
#coding:utf-8

fname='中国.txt'
dname='中国'

puts File.exist?(fname) #false
puts Dir.exist?(dname) #false

puts File.exist?(fname.encode('gbk')) #true
puts Dir.exist?(dname.encode('gbk')) #true

File.open(fname,'r'){|f|puts f.readline.encoding} #GBK
File.open(fname.encode('gbk'),'r'){|f|puts f.readline.encoding} #GBK

Dir.foreach(dname.encode('gbk')){|d|puts d} #.和..
Dir.foreach(dname){|d|puts d} #No such file or directory - 中国 (Errno::ENOENT)

Encoding.default_external='utf-8'

puts File.exist?(fname) #false
puts Dir.exist?(dname) #false

puts File.exist?(fname.encode('gbk')) #true
puts Dir.exist?(dname.encode('gbk')) #true

File.open(fname,'r'){|f|puts f.readline.encoding} #UTF-8
File.open(fname.encode('gbk'),'r'){|f|puts f.readline.encoding} #UTF-8

Dir.foreach(dname.encode('gbk')){|d|puts d} #.和..
Dir.foreach(dname){|d|puts d} #No such file or directory - 中国 (Errno::ENOENT)
[/code]
为什么File.exist?(fname)和Dir.exist?(dname)都为false,但是File.open没有异常?
另外,怎么读取并处理UTF-16LE编码的文本?
[b]问题补充:[/b]
首先谢谢night_stalker 的解答!

文件名在中文xp下默认应该GBK编码的,所以我把代码里的字符串编码为gbk就可以找到了。否则,ruby就用我设置的utf-8编码,所以找不到。但是我疑惑的是,同样是找不到[code="ruby"]
puts File.exist?(fname) #false

puts Dir.exist?(dname) #false
[/code]File.open可以顺利通过,但是Dir.open就会异常。
还有night_stalker给的读取utf-16le编码的代码,我运行了为什么不行?
[code="ruby"]
#encoding:utf-8
File.open('a.txt','r:utf-16le'){|f|
f.read
}
#in `initialize': ASCII incompatible encoding needs binmode (ArgumentError)
[/code]
[b]问题补充:[/b]
:idea:
night_stalker的方法确实很好,最后还有个问题希望解答一下:
为什么这样转换后\r\n变成\n\n了?怎么解决?

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • xenocide 2009-08-21 13:06
    已采纳

    [quote]为什么这样转换后\r\n变成\n\n了?[/quote]
    我也不知道为什么 ……

    似乎下面这两个方法就不会 ……
    [code="ruby"]
    s = File.binread '3.txt' # 这时 s 无编码
    s.encode 'gbk', 'utf-16le', undef: :replace, replace: ''[/code]

    [code="ruby"]

    coding: utf-8

    s = File.open '3.txt', 'rb:utf-16le' do |f| # 原来加个 b 就行了 - -
    f.read
    end # 这时 s 是 utf-8
    puts s.encode 'gbk'[/code]

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • xenocide 2009-08-20 19:07

    文件名字符串最好用外部编码。修改 Encoding.default_external 没效果的。

    (首行的注释决定 Encoding.default_internal)

    读取一个 utf-16le 编码的文件:
    [code="ruby"]
    File.open 'somefile','r:utf-16le' do |f|
    f.read # 读出来的字符串编码是 default_internal
    end[/code]

    如果不知道文件的编码,可以用 'r:ascii-8bit' 选项,这个编码相当于无 encoding。

    文件名表现有点怪异,最好都用 default_external ……

    评论
    解决 无用
    打赏 举报
  • xenocide 2009-08-21 10:51

    sorry,没注意到读文件也是不能用 ascii 不兼容编码的 …… 修改版可以运行:

    试试这个
    [code="ruby"]# coding: utf-8
    s = File.open '1.txt', 'r:ascii-8bit' do |f|
    f.read
    end
    s.encode 'utf-8', 'utf-16le' # 从 utf-16le 转码成 utf-8[/code]

    查看更多 encode 选项:
    [code="控制台"]ri String.encode[/code]

    评论
    解决 无用
    打赏 举报
  • xenocide 2009-08-21 10:55

    另:如果 unicode 文件带有 bom,转码成 gbk 时会出现未定义编码的错误,把未定义的码位替换掉即可
    [code="ruby"]s.encode 'gbk', 'utf-16le', undef: :replace, replace: ''[/code]

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题