1,问题
在写一个统计代码行数的脚本时遇到一个问题:
代码:
file_name = "code.rb"
c = 0
File.foreach(file_name) do
|x|
next unless x !~ /^\s*(#|\s*$)/
c = c + 1
end
运行的时候报错
ArgumentError: invalid byte sequence in GBK
=~ at org/jruby/RubyRegexp.java:1486
=~ at org/jruby/RubyString.java:1652
!~ at org/jruby/RubyKernel.java:2158
__file__ at ddd.rb:20
foreach at org/jruby/RubyIO.java:3352
(root) at ddd.rb:17
提示说GBK编码中有不识别的内容。大概情况是这样(有待考证),由于使用的是中文的操作系统(win7),ruby根据系统的语言,采用对应编码方式(GBK),从文件中取得的字符串默认为GBK的格式。
file_name = "code.rb" c = 0
File.foreach(file_name) do
|x|
p x.encoding
next unless x !~ /^\s*(#|\s*$)/u
c = c + 1
end
p "1234567890".encoding
得到的结果是:
#<Encoding:GBK>
#<Encoding:GBK>
#<Encoding:GBK>
#<Encoding:US-ASCII>
从文件中取得内容是GBK的,一个普通的字符串是ASCII。
如果给rb脚本加上# -*- coding:utf-8 -*-,即:
# -*- coding:utf-8 -*-
file_name = "code.rb" c = 0
File.foreach(file_name) do
|x|
p x.encoding
next unless x !~ /^\s*(#|\s*$)/u
c = c + 1
end
p "".encoding
这时会将普通字符串的格式都默认为UTF-8,而从文件中读取的内容呢?请看结果:
#<Encoding:GBK>
#<Encoding:GBK>
#<Encoding:GBK>
#<Encoding:UTF-8>
结果显示,从文件中读取的内容和设置的rb程序编码方式是无关的。
对于要读取的文件是UTF-8格式,而取得的字符串却是GBK,做正则表达式判断的时候就会报错了。对于这种情况,可以设置取文件时采用UTF-8,好像只有open方法有此选项:
# -*- coding:utf-8 -*-
file_name = "code.rb" c=
open(file_name, "r:utf-8") do |f|
f.each do |line|
next unless line !~ /^\s*(#|\s*$)/
c = c + 1
p line.encoding
end
end p "".encoding
结果是:
#<Encoding:UTF-8>
#<Encoding:UTF-8>
#<Encoding:UTF-8>
#<Encoding:UTF-8>
2,结论:
# -*- coding:utf-8 -*-
影响的是rb代码中普通字符串的编码方式。
open(file_name, "r:utf-8")可以控制读取文件中编码方式。 查阅资料的过程中涉及到了
$KCODE = 'u' # 或者为$KCODE = 'utf-8'
《ruby程序设计268技》中说,默认的文字编码可以通过$KCODE环境变量设置,可实际操作过程中,并没有效果。
《*的程序世界》中说,给全局变量$KCODE设置适当的值,可以给不带选项的正则表达式制定编码方式。
$KCODE = 'e'
#全部的文本按照EUC-JP为基础
$KCODE = 'u'
#全部的文本按照UTF-8为基础
re = /foo 認証情報の入力/u
#UTF-8对应的正则表达式(u选项制定)
chars = 'abc 認証情報の入力'.split(//u)
#以问子伟单位分割string
附字符串的UTF-8 和GBK的转换方法:
require 'iconv'
def utf82gb(str)
Iconv.iconv("GBK",'UTF-8',str.to_s)
end
-----------------以下更新于2014年3月8日-----------
根据双飞燕《Ruby编程语言》,2.4.2源编码和默认外部编码
源编码:Ruby解释器解读脚本中的字符,通常采用编码注释来设定一个文件的源编码,例如:# coding: utf-8
默认外部编码:Ruby从文件或者流中读取内容时采用的默认编码,对于ruby来说是全局性的,基于电脑的区域设置来进行设置的,和电脑的操作系统语言相关。
脚本中打印 Encoding.default_external,输出结果是#<Encoding:GBK>,因为返回的是Encoding对象。
可以通过如下四种方式设置默认外部编码:
ruby -E utf-8
ruby -Eutf-8
ruby --encoding utf-8
ruby --encoding=utf-8