2013-05-16 26 views
7

查看Ruby的Base64.encode的源代碼,我無法確定在Base64中編碼該數據之前,將字符串轉換爲何種字符(如果有的話)。在Base64中編碼的Utf-8字符串將與在Base64中編碼的Utf-16字符串大不相同。 Ruby對此操作做出任何承諾嗎?使用Base64.encode時的Ruby字符編碼

回答

5

fine manual已經這樣說的:

encode64(BIN)
返回Base64- bin的編碼版本。

6.8:此方法與RFC 2045

RFC 2045 6.8表示的規定。 Base64內容傳輸編碼

Base64內容傳輸編碼旨在表示任意序列的八位字節的形式,不需要人爲可讀。 [...]

使用US-ASCII的65個字符的子集,可以爲每個可打印字符表示6位。 (額外65th字符, 「=」,用於表示一個特殊的處理功能。)

所以Base64的編碼字節成ASCII。如果這些字節實際上代表一個UTF-8編碼字符串,那麼UTF-8字符串將被分解成單個字節,這些字節將被轉換爲Base64;例如,如果您使用的是UTF-8字符串'µ',那麼您將最終將字節0xc20xb5(按此順序)編碼爲Base64表示"wrU=\n"。如果你從一個二進制字符串"\xc2\xb5"(它恰好與'µ'的UTF-8版本匹配)開始,那麼你將得到相同的"wrU=\n"輸出。

當你解碼"wrU=\n"時,你會得到字節"\xc2\xb5",你必須知道那些字節應該是UTF-8編碼的文本而不是一些任意的位。這就是爲什麼您將獨立的內容類型和字符集元數據附加到Base64上的原因。

同樣,如果你有一個UTF-16字符串,那麼它將被分解成字節,這些字節將被編碼,就像任何其他字節字符串。當然,由於字節順序問題,這種情況會稍微複雜一點,但這就是我們爲什麼有內容類型和字符集標題以及物料清單的原因。

重點是Base64與字節一起使用,而不是字符。什麼格式(UTF-8文本,UTF-16文本,PNG圖像......)是別人的問題。 Base64只是將一個字節流轉換爲US ASCII的一個子集,然後返回字節;這些字節的格式必須單獨指定。


我在源代碼中做了一些動作,結果可能是有趣的,即使它們不完全相關。該encode64 method很簡單:

def encode64(bin) 
    [bin].pack("m") 
end 

然後,如果你去翻Array#pack

static VALUE 
pack_pack(VALUE ary, VALUE fmt) 
{ 
    /*...*/ 
    int enc_info = 1;  /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */ 

,並留意enc_info,你會看到一個'm'格式將獨自離開enc_info所以包裝繩將作爲US-ASCII出現,所以encode64將按預期產生美國ASCII輸出。

+0

這與我在維克托答案評論中的懷疑一致。感謝您的確認。 – Brent

19

一個例子進行編碼和解碼以base64的UTF-8字符串:

text = "intérnalionálização" 
=> "intérnalionálização" 
text.encoding 
=> #<Encoding:UTF-8> 
encoded = Base64.encode64(text) 
=> "aW50w6lybmFsaW9uw6FsaXphw6fDo28=\n" 
encoded.encoding 
=> #<Encoding:US-ASCII> 
decoded = Base64.decode64(encode) 
=> "int\xC3\xA9rnalion\xC3\xA1liza\xC3\xA7\xC3\xA3o" 
decoded.encoding 
=> #<Encoding:US-ASCII> 
decoded = decoded.force_encoding('UTF-8') 
=> "intérnalionálização" 
decoded.encoding 
=> #<Encoding:UTF-8> 
+0

有趣。從decode64返回的字符串是US-ASCII幷包含一串轉義字符。我想這是一個非常好的指標,它在base64編碼之前將其轉換爲US-ASCII。 – Brent

+1

瞭解:http://api.rubyonrails.org/classes/Base64.html和http://apidock.com/ruby/Array/pack –

+1

如果您想在irb會話中嘗試Victor的代碼,請確保你首先需要'base64'。 – Gokul