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

 

 

你可能感兴趣的:(Ruby)