われがわログ

最適化アルゴリズムとかプログラミングについて書きたい

C++勉強メモ(文字コード変換&改行コード)

文字コード変換と改行コード周りで勉強したことをメモ。Windowsだけ、あるいはLinuxだけ使うならあまり考えなくてもよいが、両方対応しようとしたらちょっと面倒だったのでメモしておく。なお、本稿途中のコードでは、最後に掲載するコードをライブラリとして使っている。

UTF8のテキストを文字化けなくコンソールに出力する

Windowsだと多くの環境では文字化けするのでSJISに直す(ふと思ったが、海外版のWindowsだったらデフォルトエンコーディングどうなってるんだろう、、)。

utf8_to_term_enc(line)

Powershell Core (v.7.1.3)なら

[console]::OutputEncoding = New-Object System.Text.UTF8Encoding

とすればUTF8でも文字化けしないが、SJISで出力しておいた方が無難だろう。

ちなみに、コマンドプロンプトWindows Powershellのときはchcp 65001と入力するとUTF8を文字化けなく表示できる。

getlineの出力をtrimする

改行コードがCRLFのテキストをgetlineで読み込むと、Linuxの場合最後に'\r'がつくのでこれをtrimする。

std::ifstream input_file("input-utf8.txt");
std::string line;
while (getline_rtrim(input_file, line)) {
    cout << line << endl;
}

上2つの合わせ技

UTF8のテキストを読込&ターミナルに出力する場合は、以下のようにしておけばWindows, Linuxで同じ結果が得られる。

std::ifstream input_file("input-utf8.txt");
std::string line;
while (getline_rtrim(input_file, line)) {
    cout << utf8_to_term_enc(line) << endl;
}

LinuxでBOM付きのUTF-8を出力する

計算結果をCSVファイルに出力する際、LinuxだとエンコーディングUTF-8になってしまいExcelで開くと文字化けする。これを防止するために、CSVファイルの最初にBOMをいれる。

std::ofstream ofs("result.csv");
add_utf8_bom(ofs);

ライブラリでは、Linuxの場合ICUを使ってUTF8⇔SJIS変換を行うようにしているので、こっちを使ってもよいかも。

utf8_to_sjis("utf8 string");
sjis_to_utf8("sjis string");

210811_追記

ICUを使うと文字エンコーディングの判定ができたのでライブラリに入れてみた。

auto results =
    chardet("エンコーディングが判定できるくらい長い文章を入れる").value();
cout << "Detected encoding: " << results.enc << ", "
        << results.confidence << endl;
// Detected encoding: UTF-8, 100

ライブラリ

github.com