2013-05-16 7 views
7

RubyのBase64.encodeのソースを見ると、文字列が変換される文字コードは、Base64でエンコーディングされる前には判別できません。 Base64でエンコードされたUtf-8ストリングは、Base64でエンコードされたUtf-16ストリングとは大きく異なるでしょう。 Rubyはこの操作に関する約束をしていますか?Base64.encodeを使用するときのRuby文字のエンコーディング

答えて

5

fine manualが言って、これを有する:

encode64(ビン)
はBase64-を返しをビンのコード化されたバージョン。この方法は、RFC 2045のRFC 2045

セクション6.8に準拠してこう述べています。

6.8。 Base64 Content-Transfer-Encoding

Base64 Content-Transfer-Encodingは、人間が読める必要がない形式の任意のオクテットシーケンスを表すように設計されています。 [...]

US-ASCIIの65文字のサブセットが使用され、印刷可能な文字ごとに6ビットを表すことができます。 (余分な65文字は、 "="、特別な処理機能を示すために使用される。)

だから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文字列を使用すると、バイトに分割され、他のバイト文字列と同様にエンコードされます。もちろん、このケースはバイトオーダーの問題のためにもう少し複雑ですが、そのためにコンテンツタイプと文字セットのヘッダーとBOMがあります。

主な点は、Base64はバイトであり、文字ではないことです。どのような形式(UTF-8テキスト、UTF-16テキスト、PNG画像、...)は他の誰かの問題です。 Base64はバイトストリームをUS ASCIIのサブセットに変換してからバイトに変換するだけです。これらのバイトの形式を別々に指定する必要があります。


ソースでいくつか取り組みましたが、完全に関連性がない場合でも、結果は興味深いかもしれません。あなたはArray#packに目を通す場合

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

その後:encode64 methodは、単にこれです

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はUS 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 'をrequireする必要があります。 – Gokul

関連する問題