質問: C言語でbase64のデコーダを作成しています。自分のやり方だと、例えばエンコードされた平仮名の「あ」をデコードするときに、2バイトのデータを一度10進数に変換しました。すると33440(0x82a0)の値が計算できてSJISの2バイトの文字コード表と照らし合わせると平仮名の[あ」を指しているのですが、2バイトのデータである(0x82a0)を文字に変換して出力する方法がわかりません。 環境 win7 64bit vs 2013
回答: Base64と言うのは3バイト単位のバイナリデータをASCII文字中の特定の64文字から4文字を使って表すための方法です。元の「バイナリデータ」が何らかの文字列を表していたとしても、文字ごとの区切りが処理の区切りになることはありません。 例えば、元の文字列として`"Aあ"`なんて2文字からなる文字列を考えてみます。これをSJISのバイナリデータで表すと、 ``` 41 82 A0 ``` の3バイトになります。これをBase64に変換する場合には、`41 82 A0`の3バイトをまとめて変換する必要があります。`"A"`と`"あ"`は別の文字だからといって、文字単位で処理するとBase64にはなりません。 ``` 41 82 A0 ⇒ "QYKg" ``` こうやって、なんらかのバイナリデータが元としてある場合に、それから(`"QYKg"`のような)文字列表現を作ることが、「Base64エンコード」です。このバイナリデータがどうやって作られたのか、はBase64とは直接の関係はありません。 逆に入力としてBase64の文字列がある場合、それを4文字ごとに区切って処理します。 今仮にBase64の入力が`"QYKg"`だったとします。この場合、全体がちょうど4文字ですから、この4文字をまとめて、バイナリデータに変換しないといけません。 で、その結果が`41 82 A0`と言う3バイトのバイナリデータになります。 で、この`41 82 A0`と言う3バイトのバイナリデータを作ると言う処理が、Base64のデコードをした、と言うことになります。その3バイトが実はSJIS文字列を表しているとかなんとかは、Base64とは直接関係なく、バイナリデータをいかに文字列として解釈するのか、と言った部分になります。 (追記) この「バイナリデータをいかに文字列として解釈するのか」まで必要なのであれば、C言語の文字列のルールに従って末尾にNULを付け加えてやるだけです。例えば`binBuf`なんて十分なサイズを持った`char`配列に`len`バイト(`int`型)の「バイナリデータ」が出来ているとしたら、 ``` //...あなたのBase64デコード処理の後 binBuf[len] = '\0'; printf("result=%s\n", binBuf); //-> Aあ ``` と言ったコードを書いてやれば、一文字ずつ変換する必要なく元の文字列が表示されます。(もちろん出力先の端末の文字コードは元の文字列の文字コードと同じである必要があります。) ※Base64エンコードする前の元データに末尾のNUL文字を入れておけば、デコードした後NUL終端する必要がなくなるんですが、他言語で作ったBase64テキストと結果が違ってくるのであまりやりません。 いかがでしょうか?まだ何か違うと言う点があればおしらせください。