UTF-8は2度、3度死ぬ(その1)
この記事はブルータスお前もかの続きです。
きっかけは、ふっとしたところから
一晩たってMS932もUTF-8も、なぜか「ファイル構成」と出したつもりが、文字化けして、最初の字が「繝」になっている事に気づく。さて「繝」って何だろう?文字コードを調べてみる。
お気づきでしょう、「フ」のUTF-8の先頭2バイトをシフトJISで出すと、「繝」になるのです。そして「setlocale(LC_ALL, "")」は、今のコードページが何であれ、OSのコードページ(MS932)にセットさせるのです。また、setlocale()では、UTF-8をロケールに設定出来ません。
ここで疑問が、ではsetlocale()を取ってしまうと、何が起きるのだ?と。念のため、別の日本語行も追加しておきましょう。
>gcc main.c >a ファイル構成 abcファイル表示
おっ文字化けせずにUTF-8で出た〜。なんだよ、つまりはchcp 65001でコードページをUTF-8に変えても、setlocale()でMS932(≒シフトJIS)を持ってきてたのかよ〜orz。Windowsのsetlocale()意味不明!
再度msdnを読んでると、プログラム起動時に「setlocale(LC_ALL, "C")」を実施しているとのこと。つまり、すべての出来事はASCIIで処理される様です。非常に気持ちが悪いですが、ASCIIとUTF-8は干渉しないですし、結果的に、コードページをリロードしていないことから、UTF-8のWondows Cプログラムはsetlocale()しなければ良いのです。
重大な事忘れてた
そう、ここまですべてC言語でテストしてます。C++(g++)を実行したらどうなるのでしょう。まあ、出自が同一ですから、MS932のだめ文字は省略してUTF-8から行きましょう。
今回のサンプル(保存形式 UTF-8)
#include <iostream> int main() { std::cout << "ファイル構成" << std::endl; std::cout << "abcファイル表示" << std::endl; return 0; }
何でしょう?これ。2行目無いし。念のため、ファイルにリダイレクトして、内容を確認したところ、そちらでは問題ありませんでした。
さすがに・・・からは、情報は得られませんよ〜。仕方が無いので、ストリームI/Oの低レベルI/Fに変えてみましょう。
#include <iostream> int main() { std::cout.write("ファイル構成\n", 19); // std::cout << "abcファイル表示" << std::endl; return 0; }
(T-T)何かの呪いでしょうか?もちろん、リダイレクトしたファイルの中には、「ファイル構成」が格納されていました。
ええーい、貴様なんぞこうしてしまえ〜!!
//#include <iostream> #include <cstdio> int main() { // std::cout.write("ファイル構成\n", 19); // std::cout << "abcファイル表示" << std::endl; printf("ファイル構成\n"); printf("abcファイル表示\n"); return 0; }
おっC++(g++)でも、UTF-8が文字化けせずに出ましたね(と言うか出させたね)。ストリームI/Oに、元凶が住んでいそうですが、流石にライブラリの中まで、調べる気が起きないので…
- 結論
- C++(g++)でもprintf()を使おう。駄目だこりゃ