QA@IT

文字化けはなぜおこるのか?

2895 PV

一番始めに何を聞きたいかなのですが、私の文字コードに対する考え方が間違っているきがするのです。なので間違いを指摘していただきたいのです。
まず私がなぜこんな疑問を持ったか、現在困っている事を例に説明させていただきます。

今railsとiPhone間でデータ通信をしているのですが、文字化けが起きてしまいます。
そこでObjective-cで文字をエンコードしなおしたのですが、文字化けはなおりません。
具体的な流れとしては
サーバに"あ"というUTF-8で作った文字があり、それをiphoneがWeb経由で、データをもらう。しかしそのデータは"\u3042"という文字になってしまっていた。そこでiphone側で"\u3042"をエンコードし直して"あ"という文字を復元したい。が、UTF-8でエンコードをかけるとさらに”5Cu3042”という文字にかわってしまった。
という流れです。

ここで疑問なのは"\u3042"というデータをエンコードし直したのに、なぜ”あ”という文字がもどらないかです。
というのも自分の考えでは文字コードがなんであろうと基本になるデータ(bit毎に入れられているデータ)は常に一定。なのでそれに対してエンコードすれば必ず元に戻るのではないか考えているからです。
具体例をあげると
bitで100というデータがあってそれをUTF-8でエンコードすると"あ"という文字で表現できるとして、それをUnicodeで表現すると"aaa"という文字で表現されてしまった(文字化け状態) 
しかしそれ("aaa")を送信したとしてもbitでは100というデータであるということはかわらない。
送信先で送られてきたデータ("aaa")をUTF-8でエンコードすると"あ"という文字が復元されるはずである。
という考えです。

しかし実際には文字化けはなおっていないので、おそらく自分の考え方が間違っているであろうということはわかっているのですが、私の考えはどこがまちがっているでしょう?

回答

おそらく通信にJSONを使っているのではないですか。

だとすると、"\u3042"というのはJSONのユニコードエスケープ記法であり、つまりそれ自体はただの6バイトのascii文字列であり、キャラクターエンコーディングレベルでどうこうという話ではありません。あくまでJSONレベルでのエスケープ・アンエスケープの話です。したがって、JSONKit / Yajl / Touch JSON / SBJSONなど、一般的なObj-C用ライブラリを使ってパースすれば、何も考えなくとも普通に「あ」が取得できるはずです。

本来、UTF-8な文字列であればJSONではエスケープする必要がない(つまり「あ」はUTF-8で3バイトの「あ」としてそのまま送れる)のですが、なぜかrailsに標準でついてくるto_jsonはかなり広範囲にエスケープしてしまい、無駄が多い上にとてつもなく性能が悪いです(以前にテストしたところ、約50倍遅かった)。

さらに凶悪なことに、ActiveSupportがネイティブのjson gemをみつけると強制的にあらゆるオブジェクトのto_jsonメソッドを上書きしてしまい、その挙動を変えることは簡単ではありません。

そのあたりの詳細は、stackoverflowのほうに書きました。

http://stackoverflow.com/a/3285570/157384

サーバサイドのコストを減らすためにYajlやOjのような高速なJSONライブラリをうまく使うには、このように色々と工夫が必要です。

と、ここまで書いておいてなんですが、JSONの話でなかったらすみません。

編集 履歴 (0)
  • <<"\u3042"というのはJSONのユニコードエスケープ記法であり
    盲点でした。自分はてっきりUnicodeとは文字のエンコーディングの一種で、UTF-8やSJISと同じ物だと考えていました。
    つまりこれは”あ”という文字をいろんな物に変換するための前段階(自分の例でいうbit 100)だったんですね。

    色々勉強になりました。ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。