2016/06/13

[C#]絵文字の対策

このエントリーをはてなブックマークに追加
MySQLにインサートしようと思ったら、
MySQL Error: Incorrect string value
というエラーで止まってしまいました。

どうやら対象の文字のなかに絵文字があって、そいつが引っかかっていたようです。
1文字2バイトで表現される普通の文字と違って、絵文字は1文字が4バイト構成で表現されていて、そいつらはサロゲートペア文字というようです。

対策を考える

対策として考えたのは2つ。
  • MySQLのDBを1文字4バイトに対応させる方法
  • 絵文字を除去してしまう方法
ううむ。これって、4バイトへの対策はMySQLに丸投げしてるだけだし、絵文字除去も臭いものにフタという感じで、見方によってはどちらも雑な気がします。

そもそも絵文字なんて気にもしていなかったわけだし、晴天の霹靂のようにエラーが発生してから、どうしようかなあなんて考えている時点で遅くて、とりあえず一時しのぎの対策を講じようというのは少し危険ですね。
まあ、そんなこと言っていても始まらないので対策に飛びつく前に、少しだけ落ち着いて全体を見渡しておきましょう。
抑え込むだけではなくて、それぞれの対策の要点を理解したうえでどちらか都合のいいほうを選ぶという分には、きっと少しはマシでしょう。

DBを1文字4バイトに対応させる

MySQLは5.5以降からUTF8MB4に対応しているようなので、設定してあげればよいようです。
現在のテーブルごとの文字コードを確認するのと、指定のテーブルのキャラクターセットをutf8mb4に変更するSQLです。

-- 現在の文字コードの確認
show table status from データベース名;

-- テーブルのキャラクターセットを変更
alter table テーブル名 default character set utf8mb4;

なお、今回は除去する方針をとったので絵文字対応後の行追加は未検証です。

絵文字を除去する

絵文字を判別して除外する方法です。もしくは、よくある「〓(下駄)」のような文字に置き換えておくというのも手かもしれません。
// 絵文字を除外する
text = new string(text.Where(n => !Char.IsSurrogate(n)).ToArray());

// 絵文字を〓に置換
text = new string(text.Select(n => Char.IsSurrogate(n) ? '〓' : n).ToArray());
どちらも、やっていることは、Char配列に分解してから、一文字づつサロゲートペア文字かどうか判別しているだけ。
そのあとくっつけなおして文字列型に戻しています。

まとめ

ということで勉強になりました。
ちなみに、自分は絵文字を排除するように対応しました。
DBの設定を変えられないわけではないけれど、要件上では「めちゃくちゃ頻度が少ない」のと「残しておいて有用なことはない」と判断できたからです。
強引に除去しただけなので、文章のつながりが解らなくなるのも出るかもしれないけれど、それはやむなしってことで。

iOSやAndroidもサポートしちゃっている絵文字なので、もっと自在に扱えるようにならないといけなさそうな時流ではありますね。
しかし、この話、ちゃんと理解しようとすると深そうです。なのでこの辺で〆ておきますです…。

0 件のコメント :

コメントを投稿