tag:crieit.net,2005:https://crieit.net/tags/%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89/feed
「エンコード」の記事 - Crieit
Crieitでタグ「エンコード」に投稿された最近の記事
2020-07-15T21:47:11+09:00
https://crieit.net/tags/%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89/feed
tag:crieit.net,2005:PublicArticle/16007
2020-07-15T21:42:59+09:00
2020-07-15T21:47:11+09:00
https://crieit.net/posts/chrome-UTF-8-5f0ef9d3db43f
続・ブラウザ(chrome)のデフォルトエンコードってUTF-8じゃないの?
<p><strong>かなり雑な考察ですのでご注意ください。</strong></p>
<h2 id="今は昔"><a href="#%E4%BB%8A%E3%81%AF%E6%98%94">今は昔</a></h2>
<p>かつて<a href="https://crieit.net/posts/chrome-UTF-8">ブラウザ(chrome)のデフォルトエンコードってUTF-8じゃないの?</a>という記事を書いたのですが。<br />
こちら、タイトルが疑問文であることからもわかる通り、単なる疑問を書き殴った記事で、解決していません。<br />
ですが、私が書いた他の記事の3倍、4倍ものアクセスがあり、心苦しいというか、「なんだよ、結局わからなかったじゃねえかよ、XXX」みたいに思われてるんだろうなあ、みたいな被害妄想をする日々でして。<br />
なので、もう少しだけ頑張ってみようと思います。</p>
<h2 id="先に結論(推測)"><a href="#%E5%85%88%E3%81%AB%E7%B5%90%E8%AB%96%EF%BC%88%E6%8E%A8%E6%B8%AC%EF%BC%89">先に結論(推測)</a></h2>
<ul>
<li>もはやchromeにデフォルトエンコードというものはない。(たぶん)</li>
<li>何もエンコードに関する指定がない場合に採用されるのは、自動判別の結果(の内のどれか)である。判別できなかったらデフォルトエンコードになる、みたいな挙動ではない。(おそらく)</li>
<li>ぶっちゃけ、ちゃんとWEBサイトを作っていれば直面しない問題なので、わかってもあまり意味はない</li>
</ul>
<h2 id="とりあえず"><a href="#%E3%81%A8%E3%82%8A%E3%81%82%E3%81%88%E3%81%9A">とりあえず</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://chromium.googlesource.com/chromium/blink.git/+/master/Source">もぎゃさんの提示してくれたソース</a>を読もうと思ったんですけど……。<br />
なんだろう、これ。C++かな? 僕、C++やったことないんだよねえ……。<br />
これを機に覚えるというのも手ですが、正直そこまでの気力も時間もないし、機というほどのものでもないし、いきなりこのコードを読むのは辛いので、<strong>エンジニアらしからぬ感じで</strong>調べていこうと思います。</p>
<p>とりあえず、ソースを落としてきます。<br />
で、調べます。<br />
状況としては、「UTF-8になって欲しいものがShift_JISになってしまっている」ということなので、<strong>Shift_JISでgrepかけます。</strong><br />
馬鹿みたいで、期待薄ですが、とりあえずかけます。<br />
VSCodeとか駆使しても良いですが、C++の拡張とかよくわからないので原始的にいきます。</p>
<pre><code class="sh">$ 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");
</code></pre>
<p>……お?<br />
下のはshift-jisを正しくShift_JISにしている感じ? ちょっと関係なさそう。<br />
では、上のを見てみますか。TextEncodingDetectorなんて、いかにもそれっぽいじゃないですか。見るとなんか、コメントっぽいですね。</p>
<pre><code class="c"> // 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);
</code></pre>
<p>とりあえずGoogle翻訳にかけます。<br />
<em>これまでに一致するものが見つからない場合は、一番上の一致を選択します。<br />
これは、たとえばEUC-JPの親フレームが<br />
Shift_JISの子フレームで、両方のフレームでエンコードが指定されていない<br />
自動検出機能がオンになっている場合。</em><br />
ふむふむ。たぶん、「一番上」ってのは</p>
<pre><code class="c">matches[0]
</code></pre>
<p>のことでしょう。では、matchesを入れてるのはというと、ちょい上に</p>
<pre><code class="c">const UCharsetMatch** matches = ucsdet_detectAll(detector, &matchesCount, &status);
</code></pre>
<p>おー。……なんでしょうucsdet_detectAllって?<br />
grepかけても出てこないので、何かのライブラリかな?<br />
ということでググります。</p>
<p>どうやら<a target="_blank" rel="nofollow noopener" href="https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/ucsdet_8h.html">ICU</a>というもので、<a target="_blank" rel="nofollow noopener" href="http://ykot.hateblo.jp/entry/20110112/1294821848">文字コード判定ができるもの</a>のようです。<br />
なんかそれっぽい。<br />
ただ、100%の精度ではないようで、複数の結果が返ってきたりすると。つまり、UTF-8だとかShift_JISだとかが配列になって返ってくるのかな。</p>
<p>で、</p>
<pre><code class="c">WTF::TextEncoding hintEncoding(hintEncodingName);
// (中略)
const char* matchEncoding = ucsdet_getName(matches[i], &status);
//(中略)
if (WTF::TextEncoding(matchEncoding) == hintEncoding) {
encoding = hintEncodingName;
break;
}
</code></pre>
<p>んー、hintEncodingは引数で受け取ったhintEncodingNameからゴニョゴニョした感じっぽい。<br />
こいつ自身は/core/html/parser/TextResourceDecoder.cppから呼ばれてるっぽいな。</p>
<pre><code class="c">if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding))
setEncoding(detectedEncoding, EncodingFromContentSniffing);
</code></pre>
<p>それっぽい。</p>
<h2 id="そろそろ限界"><a href="#%E3%81%9D%E3%82%8D%E3%81%9D%E3%82%8D%E9%99%90%E7%95%8C">そろそろ限界</a></h2>
<p>そろそろ雰囲気だけで読むのは限界です……。<br />
何となく、metaタグやwebサーバーのレスポンスヘッダなどで指定されたエンコードと、ICUの判定結果を突合して一致したものをエンコードとしてるような気がする。<br />
で、一致しなかった場合、ICUの判定結果の0番目を採用する感じかな。<br />
これ以上は限界。</p>
<h2 id="遊んでみる"><a href="#%E9%81%8A%E3%82%93%E3%81%A7%E3%81%BF%E3%82%8B">遊んでみる</a></h2>
<p>こんなコードを書いてみます。で、いろんなエンコードで保存します。</p>
<pre><code class="html"><html>
<head>
</head>
<body>
てすと
<p id="charset"></p>
</body>
<script type="text/javascript">
document.getElementById('charset').innerText = document.characterSet
</script>
</html>
</code></pre>
<h3 id="UTF-8"><a href="#UTF-8">UTF-8</a></h3>
<p><a href="https://crieit.now.sh/upload_images/b4e7ccc0fa53a881f6b3b0f9843f0ac25efc2f0c6b0c3.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b4e7ccc0fa53a881f6b3b0f9843f0ac25efc2f0c6b0c3.png?mw=700" alt="image" /></a><br />
たぶん、UTF-8もShift_JISも検出してるけど、Shift_JISの方が先って感じなのかな? アルファベット順かな?</p>
<h3 id="Shift_JIS"><a href="#Shift_JIS">Shift_JIS</a></h3>
<p><a href="https://crieit.now.sh/upload_images/1d242b199842e3f464b872ff003bdce95efc2f390b029.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/1d242b199842e3f464b872ff003bdce95efc2f390b029.png?mw=700" alt="image" /></a><br />
なるほどそうなるよね</p>
<h3 id="EUC"><a href="#EUC">EUC</a></h3>
<p><a href="https://crieit.now.sh/upload_images/a10d542dd8e60570fefae9a2252b6bb25efc2f48bb917.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/a10d542dd8e60570fefae9a2252b6bb25efc2f48bb917.png?mw=700" alt="image" /></a><br />
おっと? 一応表示されたけどGBKって何?<br />
と思ったら簡体字用のエンコードなのね。まさかの中国語判定。</p>
<h3 id="ちなみにutf-8のファイルをwebサーバー通さずにファイル表示すると"><a href="#%E3%81%A1%E3%81%AA%E3%81%BF%E3%81%AButf-8%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E9%80%9A%E3%81%95%E3%81%9A%E3%81%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B%E3%81%A8">ちなみにutf-8のファイルをwebサーバー通さずにファイル表示すると</a></h3>
<p><a href="https://crieit.now.sh/upload_images/0a6dd05da4378d2541e95beca5646ad15efc2f646522d.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/0a6dd05da4378d2541e95beca5646ad15efc2f646522d.png?mw=700" alt="image" /></a><br />
なんで?<br />
きっとhintEncodingに何か入ってるんだろうけど……。確かに、ファイルを直で見れるので、Webサーバー通すより何かしらの情報はありそう。ただ、調べるにはちょっと力量の限界。</p>
<h2 id="その他"><a href="#%E3%81%9D%E3%81%AE%E4%BB%96">その他</a></h2>
<p>前の記事のコメントで、apacheでは文字化けしてIISでは文字化けしなかったみたいなこと言いましたけど、改めて検証したらIISでもちゃんと?文字化けしました。(この調査結果だとそりゃそうなんですが)<br />
たぶん、何か環境構築とか検証方法を間違えてたんだと思いますが……。<br />
もちろん、nginxでも文字化けします。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<ul>
<li>結論としては最初に言った通り</li>
<li>雑な考察なので信用に足るかは怪しい</li>
<li>わかる人は優しく教えてください</li>
<li>metaタグ等でエンコードはちゃんと設定しよう</li>
</ul>
hammhiko
tag:crieit.net,2005:PublicArticle/14890
2019-03-28T19:12:26+09:00
2019-03-28T19:12:26+09:00
https://crieit.net/posts/chrome-UTF-8
ブラウザ(chrome)のデフォルトエンコードってUTF-8じゃないの?
<p>まー、困ることはないんだけど、気になって気になって</p>
<h1 id="発端"><a href="#%E7%99%BA%E7%AB%AF">発端</a></h1>
<p>よく、jsとかの挙動で「あれ、どうだっけ?」ってなった時、</p>
<pre><code><html>
<head>
</head>
<body>
<button onclick="test()">
test
</button>
<script src="index.js">
</body>
</html>
</code></pre>
<p>とかで、</p>
<pre><code>docker run -d -p 8888:80 -v `pwd`:/usr/local/apache2/htdocs httpd
</code></pre>
<p>で、さくっと試したりする。(果たしてこれがさくっとなのか)<br />
まー、見てわかる通り、htmlはあまりにも手抜きすぎるんだけど。<br />
動くし、すぐ使い終わるから。</p>
<p>んで、ある時、</p>
<pre><code><html>
<head>
</head>
<body>
<button onclick="test()">
てすと
</button>
<script src="index.js">
</body>
</html>
</code></pre>
<p>ってやったら、見事に文字化けした。<br />
(macのchrome)</p>
<h1 id="対処はわかる。わかるんだけど…"><a href="#%E5%AF%BE%E5%87%A6%E3%81%AF%E3%82%8F%E3%81%8B%E3%82%8B%E3%80%82%E3%82%8F%E3%81%8B%E3%82%8B%E3%82%93%E3%81%A0%E3%81%91%E3%81%A9%E2%80%A6">対処はわかる。わかるんだけど…</a></h1>
<p>対処としては簡単で、</p>
<pre><code><html>
<head>
<meta charset="utf-8"></meta>
</head>
<body>
<button onclick="test()">
てすと
</button>
<script src="index.js">
</body>
</html>
</code></pre>
<p>metaタグでcharset指定するだけなんだけど。</p>
<p>ファイル自体はUTF-8で作成していたし、UTF-8なら大丈夫だろ、とか思ってたからちょっとびっくりした。<br />
デフォルトでUTF-8じゃないのか。<br />
気になったので調べようと思った。</p>
<h1 id="調べた"><a href="#%E8%AA%BF%E3%81%B9%E3%81%9F">調べた</a></h1>
<h1 id="わかんなかった"><a href="#%E3%82%8F%E3%81%8B%E3%82%93%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F">わかんなかった</a></h1>
<p>「指定しないと文字化けする可能性があるので、ちゃんと指定しましょう」<br />
そんなことはわかってるんだ。<br />
わかった上で、指定しなかったらどうなるか知りたいんだ。<br />
指定しなかったら文字化けする? 違う、そうじゃない。いや、そうなんだけど、そうじゃない。知りたいのはそこじゃない。どのエンコーディングが採用されるのか、だ。</p>
<p>apacheにAddDefaultCharsetとかなかったし、ブラウザ側だと思うんだけどなー。</p>
<p>それっぽいこと書いてある<a target="_blank" rel="nofollow noopener" href="http://www.ic.daito.ac.jp/~mizutani/html/default_encode.html">サイト</a>もあったが、ちょっと古い。<br />
chrome ver.35って。俺のchrome、ver.73だぞ。そんな項目ねーよ。<br />
というか、chromeは<a target="_blank" rel="nofollow noopener" href="https://www.beginnerweb.net/chrome.html">もうエンコード指定できない</a>。<br />
まー、大半のユーザーは「エンコードとは何ぞ」って感じだから、意識させないってのは、わからなくもない。charset指定しないサイトなんて今時ないだろうし。でも、だからこそ、なおのこと指定しなかった場合の挙動がよくわからん。</p>
<p>普段、ちゃんと作る時は、まず間違いなく指定するmetaタグだし、わからなくても困らないっちゃ困らないし、不毛なので調べるのをやめた。</p>
<h1 id="結論"><a href="#%E7%B5%90%E8%AB%96">結論</a></h1>
<ul>
<li>エンコードはちゃんと指定しよう</li>
<li>どなたか、ご存知でしたら優しく教えてください。</li>
</ul>
hammhiko