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