(携帯電話の表情フィルタ)Emojiとunicode特殊文字の処理
Emoji表情は使用中に、わけがわからずに消えたり、文字化けしたりして、データベースにインポートしたとき、文字が見えなくなったりして、不思議に消えてしまいました!
いくつかの主要な知識点:unicodeは論理的に17個のPlaneに分けられ、各Planeは65536個のコード点を保存する.Javaのcharは最大2バイト(16 bit)しかありません.つまり、65536文字しか記憶できませんが、0 x 10000より大きい文字はどう処理しますか.この方法はjavaも婉曲な方法で解決しましたCharacterですcodePoint()はintで格納されます.コードを直接見てください.コードにはコメントがあります.
package etna.core.util; import org.eclipse.jetty.util.StringUtil; import com.google.common.base.Strings; import com.google.common.hash.Hashing;/** *='0'&&ch<='9')|(ch>='a'&&ch<='f')){hexchars[j]=ch;}else{//文字範囲がsb.append(sourceChar[index]);index++;break; } } sb.append(Character.toChars(Integer.parseInt(new String(hexchars), 16))); index += (4 + length);//4ビットプレフィックス+4-6ビット文字コード}else if(sourceChar[index+1]==unicode_prefix){//汎用文字の反転//第2平面上のものは、既に我々独自のトランスコードフォーマットを採用しているので、ここでは固定長4 char[hexchars=new char[4]; for(int j=0;j<4;j++){char ch=sourceChar[index+2+j];//2ビット識別コードif((ch>='0'&&ch<='9')|(ch>='a'&&ch<='f'){hexchars[j] = ch;//4ビット識別コード}else{//文字範囲がsb.append(sourceChar[index]);index++;break; } sb.append(Character.toChars(Integer.parseInt(String.valueOf(hexchars), 16))); index += (2 + 4);//2ビット接頭辞+4ビット文字コード}}else{sb.append(sourceChar[index]);index++;continue; } } else { sb.append(sourceChar[index]); index++; continue; } } return sb.toString(); } public static String filter(String src) { if (src == null) { return null; } int cpCount = src.codePointCount(0, src.length()); int firCodeIndex = src.offsetByCodePoints(0, 0); int lstCodeIndex = src.offsetByCodePoints(0, cpCount - 1); StringBuilder sb = new StringBuilder(src.length()); for (int index = firCodeIndex; index <= lstCodeIndex;) { int codepoint = src.codePointAt(index); if (!isEmojiCharacter(codepoint)) { System.err.println("codepoint:"+ Integer.toHexString(codepoint)); sb.append((char) codepoint); } index += ((Character.isSupplementaryCodePoint(codepoint)) ? 2 : 1); } return sb.toString(); } }
いくつかの主要な知識点:unicodeは論理的に17個のPlaneに分けられ、各Planeは65536個のコード点を保存する.Javaのcharは最大2バイト(16 bit)しかありません.つまり、65536文字しか記憶できませんが、0 x 10000より大きい文字はどう処理しますか.この方法はjavaも婉曲な方法で解決しましたCharacterですcodePoint()はintで格納されます.コードを直接見てください.コードにはコメントがあります.
package etna.core.util; import org.eclipse.jetty.util.StringUtil; import com.google.common.base.Strings; import com.google.common.hash.Hashing;/** *
* emoji , unicode , unicode emoji
*
*
* :
*
* Unicode ,
* BMP charAt(index) , length()
* , codePointAt(index), codePointCount(0,str.lenght())
*
* Unicode 17 (Plane), 65536( = 216) ,
* 。
* 0 (0000–FFFF): (Basic Multilingual Plane, BMP).
* 1 (10000–1FFFF): (Supplementary Multilingual Plane, SMP).
* 2 (20000–2FFFF): (Supplementary Ideographic Plane, SIP).
* 3 (30000–3FFFF): (Tertiary Ideographic Plane, TIP).
* 4 to 13 (40000–DFFFF)
* 14 (E0000–EFFFF): (Supplementary Special-purpose Plane, SSP)
* 15 (F0000–FFFFF) (Private Use Area, PUA)
* 16 (100000–10FFFF), (Private Use Area, PUA)
*
* :
* : http://en.wikipedia.org/wiki/Emoji
* GITHUB: http://punchdrunker.github.io/iOSEmoji/
* :1F300-1F5FF
* :1F600-1F64F
* :1F680-1F6FF
* :2600-26FF
* :2700-27BF
* :1F100-1F1FF
* :2B00-2BFF 2900-297F
* :2300-23FF
* : 2100–214F
* : 303D 3200–32FF 2049 203C
* Private Use Area:E000-F8FF;
* High Surrogates D800..DB7F;
* High Private Use Surrogates DB80..DBFF
* Low Surrogates DC00..DFFF D800-DFFF E000-F8FF
* :2000-200F 2028-202F 205F 2065-206F
* :IOS FE00-FE0F
*
* * @author Yan.xu*@version 1.0*@date 2017年3月09日*/public class EmojiCharacterUtil{//エスケープ時private static final char unicode_separator='&';private static final char unicode_prefix='u';private static final char separator=':';private static boolean isEmojiCharacter(int codePoint){return(codePoint>=0 x 2600&&codePoint<=0 x 27 BF)/雑種記号と記号フォント||codePoint==0 x 303 D||codePoint==0 x 2049||codePoint==0 x 203 C|(codePoint>=0 x 2000&&codePoint<=0 x 200 F)//|(codePoint>=0 x 2028&&codePoint<=0 x 202 F)//||codePoint==0 x 205 F//|(codePoint>=0 x 2065&&codePoint<=0 x 206 F)///*句読点占有領域*/|(codePoint>=0 x 2100&&codePoint<=0 x 214 F)//アルファベット記号||(codePoint>=0 x 2300&&&codePoint<=0 x 23 FF)/各種技術記号|(codePoint>=0 x 2 B 00&&codePoint<=0 x 2 BFF)/矢印A|(codePoint>=0 x 290&&codePoint<=0 x 297 F)/矢印B|(codePoint>=0 x 3200&&codePoint<=0 x 32 FF)/中国語記号||(codePoint>=0 xD 800&&codePoint<=0 xDFF)/高低位置換子保持領域|(codePoint>=0 xE 000&&codePoint<=0 xF 8 FF)/プライベート保持領域|(codePoint>=0 xFE 00&&codePoint<=0 xFE 0 F)//変異セレクタ||codePoint>=0 x 10000;Planeが第2平面以上の場合、charは保存できません.すべてを回転します}/***emoji文字の文字列を可視文字ID*/public static String escape(String src){if(src==null){return null; } int cpCount = src.codePointCount(0, src.length()); int firCodeIndex = src.offsetByCodePoints(0, 0); int lstCodeIndex = src.offsetByCodePoints(0, cpCount - 1); StringBuilder sb = new StringBuilder(src.length()); for (int index = firCodeIndex; index <= lstCodeIndex;) { int codepoint = src.codePointAt(index); if (isEmojiCharacter(codepoint)) { String hash = Integer.toHexString(codepoint); sb.append(unicode_separator).append(hash.length()).append(unicode_prefix).append(separator).append(hash); } else { sb.append((char) codepoint); } } return sb.toString(); }/**解析可視文字識別文字列*/public static String reverse(String src){//対応する符号化された識別ビットif(src==null){return null; } StringBuilder sb = new StringBuilder(src.length()); char[] sourceChar = src.toCharArray(); int index = 0; while (index < sourceChar.length) { if (sourceChar[index] == unicode_separator) { if (index + 6 >= sourceChar.length) { sb.append(sourceChar[index]); index++; continue;//自分のフォーマット、汎用unicode形式とは相互に回転できないif(sourceChar[index+1]>='4'&&sourceChar[index+1]<='6'&&sourceChar[index+2]==unicode_prefix&&sourceChar[index+3]==separator){int length=Integer.parseInt(String.valueOf(sourceChar[index+1]));char[] hexchars = new char[length];//4~6ビットの配列を作成します.uncodeコードのHEX値for(int j=0;j