メールや掲示板等の文章を見ていると時々「🗿」のような絵文字が出てきますが、これはUnicodeにより定義されています。
このような絵文字を取り扱うには少々知識が必要なので、この記事を通して必要な知識をお伝えしたいと思います。
また、絵文字を含む文字列を1文字ずつ切り出すjavaのサンプルコードも作りました。
【絵文字の定義と背景】
絵文字は符号化文字集合「Unicode」で定義されており、Unicodeの文字符号化方式である「UTF-8」「UTF-16」等で使用することができる。
(「符号化文字集合」とは「文字」と「文字に割り当てた番号」の対応表、「文字符号化方式」とは「文字に割り当てた番号」と「実際にコンピュータが扱う数字」の対応表のことである)
なお、「UTF-16」は狭義の「Unicode」として呼ばれることもある。
Unicodeは元々1~2バイト文字を定義していたが、世界中の文字を取り扱いたいという要望に応えるために4バイト文字を拡張領域として定義した。
絵文字は、この拡張領域に含まれる。
4バイト文字は、「上位サロゲート(2バイト)+下位サロゲート(2文字)」の組み合わせで定義される。
「上位サロゲート」は0xD800~0xDBFF(1024通り)、「下位サロゲート」は0xDC00~0xDFFF(1024通り)で定義され、何れも2バイト文字では使用しないコードであるため、表現が衝突することはない。
4バイト文字は定義当時は実際に扱われることが少なかったが、日本の携帯の絵文字の普及により一般的に使われるようになり、Webシステム等では無視できない存在となった。
【サンプルコード】
・ソースコード(UTF-8で作成)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class Sample { public static void main(String args[]){ // 変数で直接4バイト文字込みの文字列を定義し表示 String str = "🚅Unicode🌏絵文字で遊んでみよう😮"; System.out.println("変数から取得:"+str); // 何も考えず1文字ごと文字と文字コードを出力 // 4バイト文字は2文字扱い for (int i = 0; i < str.length() ; i++) { int code = (int)str.charAt(i); String hex = Integer.toHexString(code); System.out.println ((i + 1) + "番目の文字:" + str.charAt(i) + " 16進数:" + hex); } // サロゲート文字で4バイト文字を判定 // 正しく1文字ずつ切り出す String upperSurStart = "d800"; String upperSurEnd = "dbff"; int fourByteMojiCount = 0; for (int i = 0; i < str.length() ; i++) { int mojiPos = i+1-fourByteMojiCount; int code = (int)str.charAt(i); String hex = Integer.toHexString(code); String strOneMoji = ""; if (hex.compareTo(upperSurStart)>=0 && hex.compareTo(upperSurEnd)<=0) { strOneMoji = str.substring(i,i+2); i++; fourByteMojiCount++; } else { strOneMoji = str.substring(i,i+1); } System.out.println(mojiPos + "番目の文字:" + strOneMoji); } } } |
・出力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
変数から取得:🚅Unicode🌏絵文字で遊んでみよう😮 1番目の文字:? 16進数:d83d 2番目の文字:? 16進数:de85 3番目の文字:U 16進数:55 4番目の文字:n 16進数:6e 5番目の文字:i 16進数:69 6番目の文字:c 16進数:63 7番目の文字:o 16進数:6f 8番目の文字:d 16進数:64 9番目の文字:e 16進数:65 10番目の文字:? 16進数:d83c 11番目の文字:? 16進数:df0f 12番目の文字:絵 16進数:7d75 13番目の文字:文 16進数:6587 14番目の文字:字 16進数:5b57 15番目の文字:で 16進数:3067 16番目の文字:遊 16進数:904a 17番目の文字:ん 16進数:3093 18番目の文字:で 16進数:3067 19番目の文字:み 16進数:307f 20番目の文字:よ 16進数:3088 21番目の文字:う 16進数:3046 22番目の文字:? 16進数:d83d 23番目の文字:? 16進数:de2e 1番目の文字:🚅 2番目の文字:U 3番目の文字:n 4番目の文字:i 5番目の文字:c 6番目の文字:o 7番目の文字:d 8番目の文字:e 9番目の文字:🌏 10番目の文字:絵 11番目の文字:文 12番目の文字:字 13番目の文字:で 14番目の文字:遊 15番目の文字:ん 16番目の文字:で 17番目の文字:み 18番目の文字:よ 19番目の文字:う 20番目の文字:😮 |
文字の16進数表現は奥深いです。
先日公開したゾーン10進数・パック10進数もそうですが、文字が16進数でどのように表現されているのかを意識しないとコーディングに支障をきたすこともあります。
新人の時は16進数をあまり意識しておらず、エラーが出てもその理由がわからなかったりして色々苦労しました…。
今後も、文字の16進数表現でお伝えできることがあれば、記事にしていきたいと思います!
コメント