[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了?怎么解决?
[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"]
s = File.open '3.txt', 'rb:utf-16le' do |f| # 原来加个 b 就行了 - -
f.read
end # 这时 s 是 utf-8
puts s.encode 'gbk'[/code]
文件名字符串最好用外部编码。修改 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 ……
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]
另:如果 unicode 文件带有 bom,转码成 gbk 时会出现未定义编码的错误,把未定义的码位替换掉即可
[code="ruby"]s.encode 'gbk', 'utf-16le', undef: :replace, replace: ''[/code]