ruby 程序中的文字编码
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 "1234567890".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= 0
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 "1234567890".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