C++はUnicodeの文字列の変換機能があるにはあるが非推奨なので、外部ライブラリを使わなければならない。utfcppはBoost Software License 1.0で使える、ヘッダオンリーのutf変換ライブラリ。特にutf8が得意。
ダウンロード:
https://github.com/nemtrif/utfcpp
ヘッダオンリーなのでCMakeは不要。ただ一応CMakeしてinstallすると以下のような配置になる。
install │ └─include └─utf8cpp │ utf8.h │ └─utf8 checked.h core.h cpp11.h cpp17.h unchecked.h
#include <iostream> #include <fstream> #include <utf8cpp/utf8.h> int main() { std::u16string u16s = u"いろはにほへと"; // 変換結果格納先。C++20はu8stringを使える std::u8string u8s; utf8::utf16to8(u16s.begin(), u16s.end(), std::back_inserter(u8s)); // utf8文字列を保存 std::ofstream out("output.txt", std::ios::out | std::ios::binary); out.write((const char*)u8s.c_str(), u8s.size()); }
utf8::nextで次のutf8文字へ飛べる。ただし、書記素単位ではないので、結合文字を一気にジャンプしてくれない。そういう用途では使用できない。
#include <iostream> #include <fstream> #include <vector> #include <sstream> #include <utf8cpp/utf8.h> int main() { // 👨👩👧👦は結合文字。テストのために入れている。 // utf8::nextはコードポイント単位で次へいけるが、 // 書記素単位ではジャンプできないので、 // 結合文字は 文字,結合文字,文字 と分離してしまう // 結合文字を判別するのは大変なので、utfcpp std::u8string u8s = u8"いろは👨👩👧👦にほへと"; auto itr = u8s.begin(); auto iend = u8s.end(); while (itr != iend) { unsigned int codepoint = utf8::next(itr, iend);//次の文字の先頭へ移動 // コードポイントをutf8に変換 std::u8string tmp; utf8::append(codepoint, std::back_inserter(tmp)); // utf8をutf16に変換 std::u16string u16c; utf8::utf8to16(tmp.begin(), tmp.end(), std::back_inserter(u16c)); // 一文字ずつファイルに出力 static int k = 0; std::stringstream fname; fname << k++ << ".txt"; std::ofstream o(fname.str(), std::ios::out | std::ios::binary); o.write( (const char*)u16c.data(), u16c.size()*2); } }