Ruby:字符集和編碼學習總結

背景

Ruby直到1.9版本才很好的支持了多字節編碼,本文簡單總結了今天學習的關於Ruby編碼方面的知識。windows

字符串可使用不一樣的編碼

在.NET中字符串的編碼是一致的,Ruby容許字符串有不一樣的編碼,當時我就在想:若是兩個不一樣編碼的字符串相加會出現什麼結果?學習

測試程序測試

 1 # coding: utf-8
 2 
 3 str_utf8 = "hi 段"
 4 puts str_utf8.size                                # 4
 5 puts str_utf8.bytesize                            # 6
 6 puts str_utf8 .encoding                         # UTF-8
 7 str_utf8.each_byte {|b| print "%02X," % [b]}      # 68,69,20,E6,AE,B5,
 8 puts
 9 
10 puts
11 
12 str_gb2312 = "hi 段".encode("gb2312")
13 puts str_gb2312.size                            # 4
14 puts str_gb2312.bytesize                        # 5
15 puts str_gb2312 .encoding                         # GB2312
16 str_gb2312.each_byte {|b| print "%02X," % [b]}     # 68,69,20,B6,CE,
17 puts

輸出結果編碼

1 4
2 6
3 UTF-8
4 68,69,20,E6,AE,B5,
5 
6 4
7 5
8 GB2312
9 68,69,20,B6,CE,

備註:UTF-8對英文采用1個字節,對中文采用三個字節。GB2312對英文采用1個字節,對中文采用兩個字節。spa

編碼轉換

編碼轉換能夠採用String::encode("目標編碼名稱")來完成,若是編碼之間的轉換兼容,返回編碼後的字符串,不然會拋出編碼轉換異常。code

測試程序blog

1 begin
2     puts "".encode("ascii")
3 rescue Exception => e
4     puts e.class
5 end
6 
7 puts "".encode("gb2312")

輸出結果utf-8

1 Encoding::UndefinedConversionError
2

備註:encode會返回一個和元字符串序列同樣的字符串序列,只是內部的字節序列改變了。ci

編碼強制

編碼強制是指在不改變字節序列的狀況下改變對字節的解釋方式,編碼強制:String::force_encoding("強制編碼")。開發

測試程序

 1 utf8_str = "\xE6\xAE\xB5".encode("utf-8")
 2 puts utf8_str.encoding() # UTF-8
 3 puts utf8_str.size # 1
 4 puts utf8_str.bytesize # 3
 5 
 6 ascii_str = "\xE6\xAE\xB5".force_encoding("ascii")
 7 puts ascii_str.encoding() # US-ASCII
 8 puts ascii_str.size # 3
 9 puts ascii_str.bytesize # 3
10 puts ascii_str.valid_encoding? # false

輸出結果

1 UTF-8
2 1
3 3
4 US-ASCII
5 3
6 3
7 false

備註:String::valid_encoding?能夠斷定是不是有效的強制。

不一樣編碼的字符串相加後是啥結果?

這個問題的答案很簡單:若是兩個字符串的編碼兼容,則返回字符集最大的編碼,不然跑出不兼容異常。你能夠本身檢查兼容性:Encoding.compatible?。

測試程序

1 str_ascii = "hi ".encode("ascii")
2 str_utf8 = ""
3 puts str_ascii.encoding
4 puts str_utf8.encoding
5 puts Encoding.compatible?(str_ascii.encoding, str_utf8.encoding)
6 puts (str_ascii + str_utf8).encoding
7 puts (str_utf8 + str_ascii).encoding

運行結果

1 US-ASCII
2 UTF-8
3 UTF-8
4 UTF-8
5 UTF-8

一直沒使用過的\u和\x

幾乎全部的語言都支持這兩個轉義字符,容許咱們使用\uXXXX指定Unicode碼點對於的字符,通用也運行咱們使用\xXX指定字節。

測試程序

1 puts "" #
2 puts "\xE6\xAE\xB5" #
3 puts "\u6BB5" #

輸出結果

1 #
2 #
3 #

使用Sublime開發Ruby時,輸出到控制檯的字符串爲啥不能使用多種編碼?

測試程序

1 puts ""
2 puts "".encode("GB2312")

在Sublime中的輸出結果

1 [Decode error - output not utf-8]

在控制檯的輸出結果

緣由分析

Sublime之因此失敗是由於Sublime重定位了默認標準輸出流,而重定位後的流不支持混合多種編碼,說白了:你無法在一個文件中保存兩種編碼的字符串。

備註:Sublime中的失敗不是Ruby致使的,是Sublime自身的問題。

如何解決?

Sublime默認只能接收UTF8編碼,所以必須轉換爲UTF8編碼。

1 # 默認是UTF8編碼,不用處理。
2 puts ""
3 # 執行windows命令必須使用GB2312編碼。
4 command = "echo 段".encode("GB2312")
5 # 命令執行的結果想輸出到Sublime必須使用UTF8編碼。
6 puts `#{command}`.encode("utf-8")

輸出結果

1  # 輸出結果
2 3

備註

字符串、字符集和編碼算是剛入門,有機會還得繼續學習。

相關文章
相關標籤/搜索