記事最終更新日:2017/12/06
ここでは、Arduino core for ESP32 で、Unicode ( UTF16 ) 文字列を UTF-8 文字列に変換する方法を紹介します。
Arduino core for ESP32 には、xtensa – esp32 の C++ コンパイラが入っていますが、そのライブラリの中に、Linux の GCC コンパイラで使用される Unicode を変換する為に必要なライブラリと同じものが同梱されていました。
よって、ネット上で公開されている、GCC コンパイラ動作のUnicode ( UTF16 )文字列からUTF-8 へ変換するソースコードがそのまま流用できます。
Twitter API などから日本語ツイートを取得する場合、Unicode ( UTF16 )で返ってきます。
例えば、以下のような文字列
"ものづくりの根底"
の場合、
\u3082\u306E\u3065\u304F\u308A\u306E\u6839\u5E95
というように、’¥’またはバックスラッシュ ‘\’ の後に ’u’ が付いて、その後に16進数の2バイトコードで日本語1文字を表現します。
この ’¥’ またはバックスラッシュ ‘\’ が厄介で、文字列をうまく処理して16進数を取得しないと、思わぬ文字化けが生じます。
というわけで、ESP-WROOM-32 ( ESP32 )開発ボードを使って、実験してみます。
おすすめのボードは以下の2種類です。
ESPr Developer 32
USBホスト機器や ESP-WROOM-32 自体を突入電流や過電流から手厚く保護してくれるお薦めボード
ESPr Developer 32 ( スイッチサイエンス製 ) を使ってみました
ESP32-DevKitC
Espressif Systems 社純正
Arduino IDE は 1.8.5 で動作確認しています。
Arduino core for ESP32 は最新版を使用してください。
そのインストール方法や設定は以下の記事を参照してください。
Arduino core for the ESP32 のインストール方法
では、以下の Arduino スケッチを入力してみてください。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)
#include <codecvt>
#include <string>
#include <cassert>
#include <locale>
//*************************************
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.println();
String utf16_str = "\\u3082\\u306E\\u3065\\u304F\\u308A\\u306E\\u6839\\u5E95";
String utf8_str = "日本語漢字";
Serial.println("【 Unicode ( UTF16 ) 】");
Serial.println( utf16_str );
Serial.println("【 UTF16 → UTF8 】");
Serial.println( UTF16toUTF8( utf16_str ) );
}
void loop(){
}
//******************************************
String UTF16toUTF8(String str){
str.replace("\\u","\\");
str += '\0';
uint16_t len = str.length();
char16_t utf16code[len];
int i=0;
String str4 = "";
for(int j=0; j<len; j++){
if(str[j] == 0x5C){ //'\'を消去
j++;
for(int k=0; k<4; k++){
str4 += str[j+k];
}
utf16code[i] = strtol(str4.c_str(), NULL, 16); //16進文字列を16進数値に変換
str4 = "";
j = j+3;
i++;
}else if(str[j] == 0x23){ //'#'を消去
utf16code[i] = 0xFF03; //全角#に変換
i++;
}else{
utf16code[i] = (char16_t)str[j];
i++;
}
}
std::u16string u16str(utf16code);
std::string u8str = utf16_to_utf8(u16str);
String ret_str = String(u8str.c_str());
//URLに影響のある特殊文字を全角に変換
ret_str.replace("+", "+");
ret_str.replace("&", "&");
ret_str.replace("\\", "¥");
return ret_str;
}
//*****************************************************
std::string utf16_to_utf8(std::u16string const& src){
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
return converter.to_bytes(src);
}
【解説】
●1-4行:
Arduino core for ESP32 の xtensa-esp32 C++ ライブラリのインクルードです。
これは、GCC のライブラリと同じようです。
●13行:
UTF16文字列は特殊文字 ‘\’ をエスケープするために、その前に ‘\’ を付加しています。
これが無いと、1行の文字列として認識できません。
●28-63行:
UTF16 文字列から、UTF8 に変換する関数です。
まずは、’\\u’ を検出して、その後の16進数文字列を、41行目にあるように 16進数値に変換します。
変換した16進数コードを、ライブラリクラスの u16string 型に変換し、それを55行で、std::string型に変換し、それを56行で、c_str() 関数を使って const char 型に変換し、String型に変換しています。
かなりややこしいですね。
そして、’\’ や、’¥’を消去して、’#’ や’&’ などの特殊文字を全角に変えています。
●65-68行:
これは、一般的な GCC コンパイラのライブラリを使った、UTF16 から UTF8 へ変換する関数です。
std::string は Arduino IDE の String型とは異なることに注意です。
コンパイル書き込み実行
では、ESP-WROOM-32 ( ESP32 )開発ボードを接続して、Arduino IDE で コンパイル書き込みしてみてください。
間髪入れずにシリアルモニターを 115200bps で起動すると、下図の様に表示されればOKです。
以上、Arduino core for ESP32 による、日本語 Unicode ( UTF16 ) から UTF-8 へ変換する方法でした。
Amazon.co.jp 当ブログのおすすめ
コメント