かなり雑な考察ですのでご注意ください。
かつてブラウザ(chrome)のデフォルトエンコードってUTF-8じゃないの?という記事を書いたのですが。
こちら、タイトルが疑問文であることからもわかる通り、単なる疑問を書き殴った記事で、解決していません。
ですが、私が書いた他の記事の3倍、4倍ものアクセスがあり、心苦しいというか、「なんだよ、結局わからなかったじゃねえかよ、XXX」みたいに思われてるんだろうなあ、みたいな被害妄想をする日々でして。
なので、もう少しだけ頑張ってみようと思います。
もぎゃさんの提示してくれたソースを読もうと思ったんですけど……。
なんだろう、これ。C++かな? 僕、C++やったことないんだよねえ……。
これを機に覚えるというのも手ですが、正直そこまでの気力も時間もないし、機というほどのものでもないし、いきなりこのコードを読むのは辛いので、エンジニアらしからぬ感じで調べていこうと思います。
とりあえず、ソースを落としてきます。
で、調べます。
状況としては、「UTF-8になって欲しいものがShift_JISになってしまっている」ということなので、Shift_JISでgrepかけます。
馬鹿みたいで、期待薄ですが、とりあえずかけます。
VSCodeとか駆使しても良いですが、C++の拡張とかよくわからないので原始的にいきます。
$ grep -Ir Shift_JIS .
./platform/text/TextEncodingDetector.cpp: // a child frame in Shift_JIS and both frames do NOT specify the encoding
./wtf/text/TextCodecICU.cpp: registrar("shift-jis", "Shift_JIS");
……お?
下のはshift-jisを正しくShift_JISにしている感じ? ちょっと関係なさそう。
では、上のを見てみますか。TextEncodingDetectorなんて、いかにもそれっぽいじゃないですか。見るとなんか、コメントっぽいですね。
// If no match is found so far, just pick the top match.
// This can happen, say, when a parent frame in EUC-JP refers to
// a child frame in Shift_JIS and both frames do NOT specify the encoding
// making us resort to auto-detection (when it IS turned on).
if (!encoding && matchesCount > 0)
encoding = ucsdet_getName(matches[0], &status);
とりあえずGoogle翻訳にかけます。
これまでに一致するものが見つからない場合は、一番上の一致を選択します。
これは、たとえばEUC-JPの親フレームが
Shift_JISの子フレームで、両方のフレームでエンコードが指定されていない
自動検出機能がオンになっている場合。
ふむふむ。たぶん、「一番上」ってのは
matches[0]
のことでしょう。では、matchesを入れてるのはというと、ちょい上に
const UCharsetMatch** matches = ucsdet_detectAll(detector, &matchesCount, &status);
おー。……なんでしょうucsdet_detectAllって?
grepかけても出てこないので、何かのライブラリかな?
ということでググります。
どうやらICUというもので、文字コード判定ができるもののようです。
なんかそれっぽい。
ただ、100%の精度ではないようで、複数の結果が返ってきたりすると。つまり、UTF-8だとかShift_JISだとかが配列になって返ってくるのかな。
で、
WTF::TextEncoding hintEncoding(hintEncodingName);
// (中略)
const char* matchEncoding = ucsdet_getName(matches[i], &status);
//(中略)
if (WTF::TextEncoding(matchEncoding) == hintEncoding) {
encoding = hintEncodingName;
break;
}
んー、hintEncodingは引数で受け取ったhintEncodingNameからゴニョゴニョした感じっぽい。
こいつ自身は/core/html/parser/TextResourceDecoder.cppから呼ばれてるっぽいな。
if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding))
setEncoding(detectedEncoding, EncodingFromContentSniffing);
それっぽい。
そろそろ雰囲気だけで読むのは限界です……。
何となく、metaタグやwebサーバーのレスポンスヘッダなどで指定されたエンコードと、ICUの判定結果を突合して一致したものをエンコードとしてるような気がする。
で、一致しなかった場合、ICUの判定結果の0番目を採用する感じかな。
これ以上は限界。
こんなコードを書いてみます。で、いろんなエンコードで保存します。
<html>
<head>
</head>
<body>
てすと
<p id="charset"></p>
</body>
<script type="text/javascript">
document.getElementById('charset').innerText = document.characterSet
</script>
</html>
たぶん、UTF-8もShift_JISも検出してるけど、Shift_JISの方が先って感じなのかな? アルファベット順かな?
おっと? 一応表示されたけどGBKって何?
と思ったら簡体字用のエンコードなのね。まさかの中国語判定。
なんで?
きっとhintEncodingに何か入ってるんだろうけど……。確かに、ファイルを直で見れるので、Webサーバー通すより何かしらの情報はありそう。ただ、調べるにはちょっと力量の限界。
前の記事のコメントで、apacheでは文字化けしてIISでは文字化けしなかったみたいなこと言いましたけど、改めて検証したらIISでもちゃんと?文字化けしました。(この調査結果だとそりゃそうなんですが)
たぶん、何か環境構築とか検証方法を間違えてたんだと思いますが……。
もちろん、nginxでも文字化けします。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント