Ruby Ruby 1.9 中文处理

tsinghan · 2012年05月04日 · 最后由 comme 回复于 2012年05月10日 · 9855 次阅读

ruby1.9 中文处理

ruby 1.9 版本中,代码中出现中文会抛出:invalid multibyte char (US-ASCII) 异常。ruby1.9 默认的编码为 US-ASCII。所依会抛出异常。

1.9 的这种改进 有什么好处呢?

支持 unicode 呀,虽然也不好用。

在文件首加上 # encoding: utf-8 就行了 ruby1.9 的 unicode 支持非常好。比 1.8 和 python 強得太多。是我所知道的編程語言中最好的。比 java\javascrpt\c# 都要好,可以直接處理 cjk b/c/d(utf-8 四字節) 的字符。

不信你在 irb 上 打: ?字.ord 它會直接給出 unicode codepoint "天地玄黃".each_char{|chr| puts chr} 也是預想的結果。

#1 楼 @pongyo 恩 是的 要在文件头上 encoding: utf-8 但为什么默认的编码 改成 US-ASCII,这有什么好处?

@TsingHan 這樣 parse 的速度更快呀,那還用問嗎!

#2 楼 @charmquark 恩 对这理解不是很深,你说的“ruby1.9 的 unicode 支持非常好。比 1.8 和 python 強得太多”怎么理解?增强了哪些?

@TsingHan 1.8 本身不支持 utf-8,比如你 打 “A一大".length,得出來的不是 3,而是 7,因為 A 一個字節,「一」「大」各三個字節。

而 1.9 each_char , length之類默認的就是 utf8. "A一大".length就是 3,想知道字節數要用"A一大".bytesize

此外如「𣊫」「𥗉」之類大字集的字(4 字節,不知你看到沒),python(win 版), java,javascript 都不能自識別,要當成 surrogate pair 來處理。如 “A一𥗉大",本來只 4 個字,javascript "A一𥗉大".length得出來的卻是 5。我們要跟中文打交道,能用上 1.9 近乎完美的 utf-8 支持真是賞心樂事

#6 楼 @charmquark thank you,我试试看

#6 楼 @charmquark 你好,刚才试了试,了解了好多这方面的内容,还有一个问题想问一下,ruby 是采用 csi 方式,而其像 java 采用的 ucs 方式,这两种方式 最主要的区别是什么?

#8 楼 @TsingHan 應該是 CSI 吧,我不太清楚這個名目的具體所指。UCS除非是用UCS-4的(我所知的只有QT和linux上的python用ucs-4),一處理大字集就卡殼了(java/javascript/c#都是ucs-2)。雖有補救的辦法,但是很麻煩,比如python,win32上用的是ucs-2,我們編一個支持大字集的程序,從linux port 到 win 就很頭痛。說是 run everywhere,豈不成了空話!而 UCS-4 是一切字符都 4 個字節,比較浪費內存的說。但是處理效率可能會高一些,因為電腦的 word 就是 32/64 位的。

ruby 1.9 之前,本身是甚麼碼都不支持的,ruby string 就相當於 c string,只是以字節為單位。1.9 則內置了 utf-8(1 至 4 字節的不定長碼)的算法。

UCS-2 是每字符兩字節,超出 BMP 的字用 surrogate pair UCS-4 是每字符 4 字節,unicode 全包括了 utf-8 是 1-4 字節。格式為

0xxx xxxx - ASCII
110x xxxx 10xx xxxx 
1110 xxxx 10xx xxxx 10xx xxxx - 漢字 CJK  /CJK - A
1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx - 漢字 CJK-B/C/D




其中 xxx..為有效 bits,1110、10 之類是碼長標志位。 utf-8 可直接兼容 ASCII,這就是它的最大好處。中文字都是 3 碼或 4 碼,3 碼字有效位剛好為 16,正對應 ucs-2 的雙字節碼,這個空間就叫 BMP,中文 GBK\BIG 就收容在內。然而大字集收了 7 萬字,有 4 萬多是在 BMP 之外的,如用 utf-8,因算法是固化的,一般無障礙,遇到 ucs-2 就很麻煩。如 java,你得用到 codePoint() 一類的函數,若用到 swing 還往往顯示不出。若是 js,乾脆連函數也沒有,只得自己寫算法。

#8 楼 @TsingHan CSI 是指 Character Set Independent?松本那本书里面讲的应该很清楚了,java 之类的语言一开始就限定了所谓内部编码,虽然看起来很好,但是实际上受制于内部编码本身的局限性,当 unicode 被扩展以后,java 社区就不得不开发 code point 相关的 api,而且这个 api 出来的太晚,以至于很多基础类库都没有做好准备,会有潜在问题。 而 ruby 一开始没有限定,所以开发者都必须明确一点:string 本质上是字节数组,这样,开发者要决定一些和编码相关的东西。到了 1.9,ruby 标准库为开发者提供了一些便利条件,但是主动权仍然在开发者手里,这也是 ruby 哲学所一直倡导的原则

#10 楼 @fsword

到了 1.9,ruby 标准库为开发者提供了一些便利条件, 不單便利而已。1.9 的 utf-8 算法是用 C 寫的,若用 1.8,我們要麼用 ruby 寫,效率太低,要麼自己編譯 C 庫,port 又很麻煩。1.9 utf-8 直接做在 libruby.so 中。

#10 楼 @fsword 在 rails3.2 ruby1.9 开发中,如果很多文件都需要处理非 ascii 字符,难道需要在每个文件都加上 #encoding: UFT-8 这样一行。。。看着淡疼啊

楼主不看看哪国人发明的 Ruby. unicode 要是不好,行么?呵呵。

建议楼主看看松本写的那本`松本行宏的程序世界', 有详细介绍。

#12 楼 @googya 我个人其实比较喜欢这种做法,自我声明 encode,可以避免很多问题。当然,如果需要,可以写段脚本统一添加这个文件头 #11 楼 @charmquark 1.8 也不复杂吧,不需要用 ruby 写,iconv 编译不麻烦的

最简单解决方案:

export RUBYOPT='-KU'

#15 楼 @night_song 哇 放大招了。。

@night_song 我之前也是学习了这个方法搞定的 这个比较简便

#15 楼 @night_song #16 楼 @hooopo #17 楼 @icemark

-KU 在 1.9 不推荐使用,是过时的做法:

应该:

  • 通过 -E 外部编码:内部编码 来指定内外部编码。
  • 通过文件内的`编码注释'来设定文件的编码。

楼上正解,还是推荐在入口处直接设置好内外编码,免得忘记输入-E 神马的 - -。还是怀念 1.8 的编码啊 没有 1.9 这么麻烦 动不动就编码错误了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号