├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── github │ │ └── binarywang │ │ └── java │ │ └── emoji │ │ ├── EmojiConverter.java │ │ ├── EmojiReader.java │ │ ├── model │ │ └── Emoji4Unicode.java │ │ └── util │ │ └── EmojiUtils.java └── resources │ └── emoji4unicode.xml └── test └── java └── com └── github └── binarywang └── java └── emoji ├── EmojiConverterTest.java └── EmojiReaderTest.java /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [binarywang] 4 | custom: https://github.com/Wechat-Group/WxJava/blob/master/images/qrcodes/wepay.jpg?raw=true 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .classpath 3 | .project 4 | .settings/ 5 | /build/ 6 | *.pmd 7 | /.idea/ 8 | *.iml 9 | *.versionsBackup 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk8 4 | 5 | script: "mvn cobertura:cobertura" 6 | 7 | branches: 8 | only: 9 | - main 10 | 11 | notifications: 12 | email: 13 | - binarywang@vip.qq.com 14 | 15 | after_success: 16 | - bash <(curl -s https://codecov.io/bash) 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![码云Gitee](https://gitee.com/binary/java-emoji-converter/badge/star.svg?theme=blue)](https://gitee.com/binary/java-emoji-converter) 2 | [![Github](https://githubbadges.com/star.svg?user=binarywang&repo=java-emoji-converter&style=flat&background=1081C1)](https://github.com/binarywang/java-emoji-converter) 3 | [![Build Status](https://travis-ci.org/binarywang/java-emoji-converter.svg?branch=master)](https://travis-ci.org/binarywang/java-emoji-converter) 4 | [![codecov](https://codecov.io/gh/binarywang/java-emoji-converter/branch/master/graph/badge.svg)](https://codecov.io/gh/binarywang/java-emoji-converter) 5 | ![Maven Central](https://img.shields.io/maven-central/v/com.github.binarywang/java-emoji-converter.svg) 6 | 7 | # Java Emoji Converter(Emoji 表情转换工具) 8 | 9 | Emoji转换工具,便于各种规格客户端生成的Emoji字符串转换成另外一种格式。 10 | 11 | A tool to convert emoji string among each type, like softbank emoji, unicode emoji, alias emoji, html emoji. 12 | 13 | When converting softbank emoji to unicode, we utilize this file: 14 | https://raw.githubusercontent.com/googlei18n/emoji4unicode/master/data/emoji4unicode.xml 15 | 16 | ## Quick Start 快速入门 17 | 18 | Add this in your maven pom file(将以下内容加入你的maven的pom文件中): 19 | ```xml 20 | 21 | com.github.binarywang 22 | java-emoji-converter 23 | 1.0.2 24 | 25 | ``` 26 | 27 | ## Usage (from junit test):用法(摘自单元测试代码) 28 | 29 | private EmojiConverter emojiConverter = EmojiConverter.getInstance(); 30 | 31 | @Test 32 | public void testToAlias() { 33 | String str = "  An 😃😀awesome 😃😃string with a few 😃😉emojis!"; 34 | String alias = this.emojiConverter.toAlias(str); 35 | System.out.println(str); 36 | System.out.println("EmojiConverterTest.testToAlias()=====>"); 37 | System.out.println(alias); 38 | Assert.assertEquals( 39 | ":no_good: :ok_woman: :couple_with_heart:An :smiley::grinning:awesome :smiley::smiley:string with a few :smiley::wink:emojis!", 40 | alias); 41 | } 42 | 43 | @Test 44 | public void testToHtml() { 45 | String str = "  An 😀😃awesome 😃😃string with a few 😉😃emojis!"; 46 | String result = this.emojiConverter.toHtml(str); 47 | System.out.println(str); 48 | System.out.println("EmojiConverterTest.testToHtml()=====>"); 49 | System.out.println(result); 50 | Assert.assertEquals( 51 | "🙅 🙆 💑An 😀😃awesome 😃😃string with a few 😉😃emojis!", 52 | result); 53 | } 54 | 55 | @Test 56 | public void testToUnicode() { 57 | String str = "   :smiley: :grinning: :wink:"; 58 | String result = this.emojiConverter.toUnicode(str); 59 | System.err.println(str); 60 | System.err.println("EmojiConverterTest.testToUnicode()=====>"); 61 | System.err.println(result); 62 | Assert.assertEquals("🙅 🙆 💑 😃 😀 😉", result); 63 | } 64 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.github.binarywang 5 | java-emoji-converter 6 | 1.0.2 7 | jar 8 | Java Emoji Converter 9 | Java Emoji Converter 10 | https://github.com/binarywang/java-emoji-converter 11 | 12 | scm:git:https://github.com/binarywang/java-emoji-converter.git 13 | scm:git:https://github.com/binarywang/java-emoji-converter.git 14 | https://github.com/binarywang/java-emoji-converter 15 | v1.0.0 16 | 17 | 18 | 1.8 19 | 1.8 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 25 | UTF-8 26 | 27 | 28 | 29 | ossrh 30 | https://oss.sonatype.org/content/repositories/snapshots 31 | 32 | 33 | ossrh 34 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 35 | 36 | 37 | 38 | 39 | 40 | binarywang 41 | binarywang@qq.com 42 | 43 | 44 | 45 | 46 | The Apache License, Version 2.0 47 | http://www.apache.org/licenses/LICENSE-2.0.txt 48 | 49 | 50 | 51 | 52 | 53 | com.vdurmont 54 | emoji-java 55 | 5.1.1 56 | 57 | 58 | com.thoughtworks.xstream 59 | xstream 60 | 1.4.20 61 | 62 | 63 | org.slf4j 64 | slf4j-api 65 | 1.7.36 66 | 67 | 68 | org.jodd 69 | jodd-http 70 | 6.2.1 71 | 72 | 73 | org.apache.commons 74 | commons-lang3 75 | 3.12.0 76 | 77 | 78 | com.google.guava 79 | guava 80 | 32.0.0-jre 81 | 82 | 83 | joda-time 84 | joda-time 85 | 2.10.14 86 | 87 | 88 | 89 | org.slf4j 90 | slf4j-log4j12 91 | 1.7.36 92 | test 93 | 94 | 95 | 96 | org.testng 97 | testng 98 | 7.7.0 99 | test 100 | 101 | 102 | 103 | 104 | 105 | doclint-java8-disable 106 | 107 | [1.8,) 108 | 109 | 110 | -Xdoclint:none 111 | 112 | 113 | 114 | 115 | release 116 | 117 | 118 | 119 | org.codehaus.mojo 120 | cobertura-maven-plugin 121 | 2.7 122 | 123 | 124 | html 125 | xml 126 | 127 | 128 | 129 | 130 | 131 | org.apache.maven.plugins 132 | maven-source-plugin 133 | 2.2.1 134 | 135 | 136 | attach-sources 137 | 138 | jar-no-fork 139 | 140 | 141 | 142 | 143 | 144 | org.apache.maven.plugins 145 | maven-javadoc-plugin 146 | 2.9.1 147 | 148 | 149 | attach-javadocs 150 | 151 | jar 152 | 153 | 154 | 155 | 156 | ${javadoc.opts} 157 | UTF-8 158 | zh_CN 159 | 160 | 161 | 162 | org.apache.maven.plugins 163 | maven-gpg-plugin 164 | 1.5 165 | 166 | 167 | sign-artifacts 168 | verify 169 | 170 | sign 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | org.apache.maven.plugins 185 | maven-surefire-plugin 186 | 2.17 187 | 188 | true 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | org.codehaus.mojo 197 | cobertura-maven-plugin 198 | 2.7 199 | 200 | 201 | html 202 | xml 203 | 204 | 205 | 206 | 207 | 208 | org.sonatype.plugins 209 | nexus-staging-maven-plugin 210 | 1.6.3 211 | true 212 | 213 | ossrh 214 | https://oss.sonatype.org/ 215 | true 216 | 217 | 218 | 219 | org.apache.maven.plugins 220 | maven-release-plugin 221 | 2.5.1 222 | 223 | true 224 | false 225 | release 226 | deploy 227 | 228 | 229 | 230 | org.apache.maven.plugins 231 | maven-compiler-plugin 232 | 3.6.0 233 | 234 | UTF-8 235 | 236 | 237 | 238 | 239 | maven-surefire-plugin 240 | 241 | once 242 | -Dfile.encoding=UTF-8 243 | 244 | 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/java/emoji/EmojiConverter.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.java.emoji; 2 | 3 | import com.github.binarywang.java.emoji.util.EmojiUtils; 4 | import com.vdurmont.emoji.EmojiParser; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author Binary Wang 12 | */ 13 | public class EmojiConverter { 14 | private EmojiReader emojiReader = null; 15 | private final static EmojiConverter INSTANCE = new EmojiConverter(); 16 | 17 | private EmojiConverter() { 18 | } 19 | 20 | public static EmojiConverter getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | /** 25 | * convert emoji string with unicode/softbank to strings with aliases 26 | * 27 | * @param input 输入的字符串内容 28 | * @return result string 29 | */ 30 | public String toAlias(String input) { 31 | if (EmojiUtils.containsSbEmoji(input)) { 32 | input = this.sb2Unicode(input); 33 | } 34 | 35 | String result = EmojiParser.parseToAliases(input); 36 | if (result.equals(EmojiParser.parseToAliases(result))) { 37 | return result; 38 | } else { 39 | return EmojiParser.parseToAliases(result); 40 | } 41 | 42 | } 43 | 44 | private String sb2Unicode(String input) { 45 | if (this.emojiReader == null) { 46 | this.emojiReader = new EmojiReader(); 47 | } 48 | 49 | final Map, String> sb2UnicodeMap = this.emojiReader.getSb2UnicodeMap(); 50 | 51 | StringBuilder result = new StringBuilder(); 52 | int[] codePoints = toCodePointArray(input); 53 | for (int i = 0; i < codePoints.length; i++) { 54 | List key2; 55 | if (i + 1 < codePoints.length) { 56 | key2 = new ArrayList<>(); 57 | key2.add(codePoints[i]); 58 | key2.add(codePoints[i + 1]); 59 | 60 | if (sb2UnicodeMap.containsKey(key2)) { 61 | String value = sb2UnicodeMap.get(key2); 62 | if (value != null) { 63 | result.append(value); 64 | } 65 | 66 | i++; 67 | continue; 68 | } 69 | } 70 | 71 | List key1 = new ArrayList<>(); 72 | key1.add(codePoints[i]); 73 | if (sb2UnicodeMap.containsKey(key1)) { 74 | String value = sb2UnicodeMap.get(key1); 75 | if (value != null) { 76 | result.append(value); 77 | } 78 | continue; 79 | } 80 | 81 | result.append(Character.toChars(codePoints[i])); 82 | 83 | } 84 | 85 | return result.toString(); 86 | } 87 | 88 | private static int[] toCodePointArray(String str) { 89 | char[] ach = str.toCharArray(); 90 | int len = ach.length; 91 | int[] acp = new int[Character.codePointCount(ach, 0, len)]; 92 | int j = 0; 93 | 94 | for (int i = 0, cp; i < len; i += Character.charCount(cp)) { 95 | cp = Character.codePointAt(ach, i); 96 | acp[j++] = cp; 97 | } 98 | 99 | return acp; 100 | } 101 | 102 | /** 103 | * convert emoji string with unicode/softbank to strings with html code 104 | * 105 | * @param input 输入的字符串内容 106 | * @return result string 107 | */ 108 | public String toHtml(String input) { 109 | if (EmojiUtils.containsSbEmoji(input)) { 110 | input = sb2Unicode(input); 111 | } 112 | 113 | String result = EmojiParser.parseToHtmlDecimal(input); 114 | if (result.equals(EmojiParser.parseToHtmlDecimal(result))) { 115 | return result; 116 | } else { 117 | return EmojiParser.parseToHtmlDecimal(result); 118 | } 119 | } 120 | 121 | /** 122 | * convert string with softbank/alias emoji to strings with unicode 123 | * 124 | * @param input 输入的字符串内容 125 | * @return result string 126 | */ 127 | public String toUnicode(String input) { 128 | if (EmojiUtils.containsSbEmoji(input)) { 129 | input = sb2Unicode(input); 130 | } 131 | 132 | String result = EmojiParser.parseToUnicode(input); 133 | if (result.equals(EmojiParser.parseToUnicode(result))) { 134 | return result; 135 | } else { 136 | return EmojiParser.parseToUnicode(result); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/java/emoji/EmojiReader.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.java.emoji; 2 | 3 | import com.github.binarywang.java.emoji.model.Emoji4Unicode; 4 | import com.github.binarywang.java.emoji.model.Emoji4Unicode.Category; 5 | import com.github.binarywang.java.emoji.model.Emoji4Unicode.Element; 6 | import com.github.binarywang.java.emoji.model.Emoji4Unicode.SubCategory; 7 | import com.google.common.collect.Maps; 8 | import com.thoughtworks.xstream.XStream; 9 | import com.thoughtworks.xstream.io.xml.DomDriver; 10 | import com.thoughtworks.xstream.security.NoTypePermission; 11 | import com.thoughtworks.xstream.security.WildcardTypePermission; 12 | import org.joda.time.Interval; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.net.URL; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | /** 22 | * @author Binary Wang 23 | */ 24 | public class EmojiReader { 25 | private static final Logger logger = LoggerFactory.getLogger(EmojiReader.class); 26 | private static final String URL = "https://raw.githubusercontent.com/googlei18n/emoji4unicode/master/data/emoji4unicode.xml"; 27 | 28 | private static final String TRIM_PATTERN = "[^0-9A-F]*"; 29 | private Emoji4Unicode emoji = null; 30 | private Map, String> sb2UnicodeMap = null; 31 | 32 | /** 33 | * 从相关文件读取并解析得到Emoji4Unicode对象 34 | * 35 | * @param onlyFromLocal 是否只从本地读取 36 | * @return Emoji4Unicode对象 37 | */ 38 | Emoji4Unicode read(boolean onlyFromLocal) { 39 | if (emoji != null) { 40 | return emoji; 41 | } 42 | 43 | long beginTime = System.currentTimeMillis(); 44 | 45 | XStream xstream = new XStream(new DomDriver()); 46 | xstream.processAnnotations(Emoji4Unicode.class); 47 | xstream.addPermission(NoTypePermission.NONE); 48 | xstream.addPermission(new WildcardTypePermission(new String[]{"com.github.binarywang.**"})); 49 | 50 | if (onlyFromLocal) { 51 | logger.info("==============from local file=============="); 52 | emoji = (Emoji4Unicode) xstream.fromXML(EmojiReader.class.getResourceAsStream("/emoji4unicode.xml")); 53 | return emoji; 54 | } 55 | 56 | try { 57 | emoji = (Emoji4Unicode) xstream.fromXML(new URL(URL)); 58 | logger.info("==============from url=============="); 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | } 62 | 63 | if (emoji != null) { 64 | String interval = new Interval(beginTime, System.currentTimeMillis()) 65 | .toPeriod().toString().replace("PT", "").replace("M", "分") 66 | .replace("S", "秒"); 67 | logger.info("从网络读取总耗时: " + interval); 68 | return emoji; 69 | } 70 | 71 | logger.info("==============from local file=============="); 72 | emoji = (Emoji4Unicode) xstream.fromXML( 73 | EmojiReader.class.getResourceAsStream("/emoji4unicode.xml")); 74 | return emoji; 75 | 76 | } 77 | 78 | public Map, String> getSb2UnicodeMap() { 79 | if (sb2UnicodeMap != null) { 80 | return sb2UnicodeMap; 81 | } 82 | 83 | sb2UnicodeMap = Maps.newHashMap(); 84 | 85 | Emoji4Unicode emoji4Unicode = read(false); 86 | for (Category category : emoji4Unicode.getCategories()) { 87 | List subCategories = category.getSubCategories(); 88 | if (subCategories == null) { 89 | continue; 90 | } 91 | 92 | for (SubCategory subCategory : subCategories) { 93 | List elements = subCategory.getElements(); 94 | if (elements == null) { 95 | continue; 96 | } 97 | 98 | for (Element element : elements) { 99 | List fromCodePoints = new ArrayList<>(); 100 | String fromValue = element.getSoftbank(); 101 | if (fromValue == null) { 102 | continue; 103 | } 104 | 105 | if (fromValue.length() > 6) { 106 | String[] froms = fromValue.split("\\+"); 107 | for (String part : froms) { 108 | fromCodePoints.add(Integer.parseInt( 109 | part.replaceAll(TRIM_PATTERN, ""), 16)); 110 | } 111 | } else { 112 | fromCodePoints.add(Integer.parseInt( 113 | fromValue.replaceAll(TRIM_PATTERN, ""), 16)); 114 | } 115 | 116 | String toValue = element.getUnicode(); 117 | if (toValue == null) { 118 | sb2UnicodeMap.put(fromCodePoints, null); 119 | continue; 120 | } 121 | 122 | StringBuilder toBuilder = new StringBuilder(); 123 | if (toValue.length() > 6) { 124 | String[] tos = toValue.split("\\+"); 125 | for (String part : tos) { 126 | toBuilder.append(Character.toChars(Integer.parseInt( 127 | part.replaceAll(TRIM_PATTERN, ""), 16))); 128 | } 129 | } else { 130 | toBuilder.append(Character.toChars(Integer.parseInt( 131 | toValue.replaceAll(TRIM_PATTERN, ""), 16))); 132 | } 133 | 134 | sb2UnicodeMap.put(fromCodePoints, toBuilder.toString()); 135 | } 136 | } 137 | 138 | } 139 | 140 | return sb2UnicodeMap; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/java/emoji/model/Emoji4Unicode.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.java.emoji.model; 2 | 3 | 4 | import java.util.List; 5 | 6 | import org.apache.commons.lang3.builder.ToStringBuilder; 7 | import org.apache.commons.lang3.builder.ToStringStyle; 8 | 9 | import com.thoughtworks.xstream.annotations.XStreamAlias; 10 | import com.thoughtworks.xstream.annotations.XStreamAsAttribute; 11 | import com.thoughtworks.xstream.annotations.XStreamImplicit; 12 | 13 | @XStreamAlias("emoji4unicode") 14 | public class Emoji4Unicode { 15 | @XStreamImplicit(itemFieldName = "category") 16 | private List categories; 17 | 18 | @XStreamAlias("category") 19 | public static class Category { 20 | @XStreamImplicit(itemFieldName = "subcategory") 21 | private List subCategories; 22 | 23 | @XStreamAsAttribute 24 | private String name; 25 | 26 | @Override 27 | public String toString() { 28 | return toSimpleString(this); 29 | } 30 | 31 | public List getSubCategories() { 32 | return this.subCategories; 33 | } 34 | 35 | public void setSubCategories(List subCategories) { 36 | this.subCategories = subCategories; 37 | } 38 | 39 | public String getName() { 40 | return this.name; 41 | } 42 | 43 | public void setName(String name) { 44 | this.name = name; 45 | } 46 | } 47 | 48 | public static class SubCategory { 49 | @Override 50 | public String toString() { 51 | return toSimpleString(this); 52 | } 53 | 54 | @XStreamImplicit(itemFieldName = "e") 55 | private List elements; 56 | 57 | @XStreamAsAttribute 58 | private String name; 59 | 60 | public List getElements() { 61 | return this.elements; 62 | } 63 | 64 | public void setElements(List elements) { 65 | this.elements = elements; 66 | } 67 | 68 | } 69 | 70 | public static class Element { 71 | @Override 72 | public String toString() { 73 | return toSimpleString(this); 74 | } 75 | 76 | @XStreamAsAttribute 77 | private String name; 78 | 79 | @XStreamAsAttribute 80 | private String docomo; 81 | 82 | @XStreamAsAttribute 83 | private String google; 84 | 85 | @XStreamAsAttribute 86 | private String id; 87 | 88 | @XStreamAsAttribute 89 | private String kddi; 90 | 91 | @XStreamAsAttribute 92 | private String softbank; 93 | 94 | @XStreamAsAttribute 95 | private String unicode; 96 | 97 | @XStreamAsAttribute 98 | private String text_fallback; 99 | 100 | @XStreamAsAttribute 101 | private String text_repr; 102 | 103 | @XStreamAsAttribute 104 | private String img_from; 105 | 106 | @XStreamAsAttribute 107 | private String in_proposal; 108 | 109 | @XStreamAsAttribute 110 | private String glyphRefID; 111 | 112 | @XStreamAsAttribute 113 | private String oldname; 114 | 115 | @XStreamAsAttribute 116 | private String design; 117 | 118 | @XStreamImplicit(itemFieldName = "ann") 119 | private List ann; 120 | 121 | @XStreamImplicit(itemFieldName = "desc") 122 | private List desc; 123 | 124 | public String getName() { 125 | return this.name; 126 | } 127 | 128 | public void setName(String name) { 129 | this.name = name; 130 | } 131 | 132 | public String getDocomo() { 133 | return this.docomo; 134 | } 135 | 136 | public void setDocomo(String docomo) { 137 | this.docomo = docomo; 138 | } 139 | 140 | public String getGoogle() { 141 | return this.google; 142 | } 143 | 144 | public void setGoogle(String google) { 145 | this.google = google; 146 | } 147 | 148 | public String getId() { 149 | return this.id; 150 | } 151 | 152 | public void setId(String id) { 153 | this.id = id; 154 | } 155 | 156 | public String getKddi() { 157 | return this.kddi; 158 | } 159 | 160 | public void setKddi(String kddi) { 161 | this.kddi = kddi; 162 | } 163 | 164 | public String getSoftbank() { 165 | return this.softbank; 166 | } 167 | 168 | public void setSoftbank(String softbank) { 169 | this.softbank = softbank; 170 | } 171 | 172 | public String getUnicode() { 173 | return this.unicode; 174 | } 175 | 176 | public void setUnicode(String unicode) { 177 | this.unicode = unicode; 178 | } 179 | 180 | public String getText_fallback() { 181 | return this.text_fallback; 182 | } 183 | 184 | public void setText_fallback(String text_fallback) { 185 | this.text_fallback = text_fallback; 186 | } 187 | 188 | public String getText_repr() { 189 | return this.text_repr; 190 | } 191 | 192 | public void setText_repr(String text_repr) { 193 | this.text_repr = text_repr; 194 | } 195 | 196 | public String getImg_from() { 197 | return this.img_from; 198 | } 199 | 200 | public void setImg_from(String img_from) { 201 | this.img_from = img_from; 202 | } 203 | 204 | public String getIn_proposal() { 205 | return this.in_proposal; 206 | } 207 | 208 | public void setIn_proposal(String in_proposal) { 209 | this.in_proposal = in_proposal; 210 | } 211 | 212 | public String getGlyphRefID() { 213 | return this.glyphRefID; 214 | } 215 | 216 | public void setGlyphRefID(String glyphRefID) { 217 | this.glyphRefID = glyphRefID; 218 | } 219 | 220 | public String getOldname() { 221 | return this.oldname; 222 | } 223 | 224 | public void setOldname(String oldname) { 225 | this.oldname = oldname; 226 | } 227 | 228 | public List getAnn() { 229 | return this.ann; 230 | } 231 | 232 | public void setAnn(List ann) { 233 | this.ann = ann; 234 | } 235 | 236 | public List getDesc() { 237 | return this.desc; 238 | } 239 | 240 | public void setDesc(List desc) { 241 | this.desc = desc; 242 | } 243 | 244 | } 245 | 246 | public List getCategories() { 247 | return this.categories; 248 | } 249 | 250 | public void setCategories(List categories) { 251 | this.categories = categories; 252 | } 253 | 254 | private static final String LINE_SEPARATOR = "\n"; 255 | 256 | public static String toSimpleString(Object obj) { 257 | String toStringResult = ToStringBuilder.reflectionToString(obj, 258 | new SimpleToStringStyle()); 259 | String[] split = toStringResult.split(LINE_SEPARATOR); 260 | StringBuilder result = new StringBuilder(); 261 | for (String string : split) { 262 | if (string.endsWith("")) { 263 | continue; 264 | } 265 | result.append(string + LINE_SEPARATOR); 266 | } 267 | 268 | if (result.length() == 0) { 269 | return ""; 270 | } 271 | 272 | return result.deleteCharAt(result.length() - 1).toString(); 273 | } 274 | 275 | static class SimpleToStringStyle extends ToStringStyle { 276 | private static final long serialVersionUID = 7718004986394868800L; 277 | 278 | public SimpleToStringStyle() { 279 | this.setContentStart("["); 280 | this.setFieldSeparator(LINE_SEPARATOR + " "); 281 | this.setFieldSeparatorAtStart(true); 282 | this.setContentEnd(LINE_SEPARATOR + "]"); 283 | this.setUseShortClassName(true); 284 | this.setUseIdentityHashCode(false); 285 | } 286 | } 287 | } 288 | 289 | -------------------------------------------------------------------------------- /src/main/java/com/github/binarywang/java/emoji/util/EmojiUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.java.emoji.util; 2 | 3 | import java.util.Set; 4 | 5 | import com.google.common.base.Joiner; 6 | import com.google.common.collect.Sets; 7 | 8 | public class EmojiUtils { 9 | 10 | private static final char[] EMOJI_SOFTBANK_TABLE = { 0x21d4, 0x25b2, 0x25bc, 11 | 0x25cb, 0x25cf, 0x3013, 0xe001, 0xe002, 0xe003, 0xe004, 0xe005, 0xe006, 12 | 0xe007, 0xe008, 0xe009, 0xe00a, 0xe00b, 0xe00c, 0xe00d, 0xe00e, 0xe00f, 13 | 0xe010, 0xe011, 0xe012, 0xe013, 0xe014, 0xe015, 0xe016, 0xe017, 0xe018, 14 | 0xe019, 0xe01a, 0xe01b, 0xe01c, 0xe01d, 0xe01e, 0xe01f, 0xe020, 0xe021, 15 | 0xe022, 0xe023, 0xe024, 0xe025, 0xe026, 0xe027, 0xe028, 0xe029, 0xe02a, 16 | 0xe02b, 0xe02c, 0xe02d, 0xe02e, 0xe02f, 0xe030, 0xe031, 0xe032, 0xe033, 17 | 0xe034, 0xe035, 0xe036, 0xe037, 0xe038, 0xe039, 0xe03a, 0xe03b, 0xe03c, 18 | 0xe03d, 0xe03e, 0xe03f, 0xe040, 0xe041, 0xe042, 0xe043, 0xe044, 0xe045, 19 | 0xe046, 0xe047, 0xe048, 0xe049, 0xe04a, 0xe04b, 0xe04c, 0xe04d, 0xe04e, 20 | 0xe04f, 0xe050, 0xe051, 0xe052, 0xe053, 0xe054, 0xe055, 0xe056, 0xe057, 21 | 0xe058, 0xe059, 0xe05a, 0xe101, 0xe102, 0xe103, 0xe104, 0xe105, 0xe106, 22 | 0xe107, 0xe108, 0xe109, 0xe10a, 0xe10b, 0xe10c, 0xe10d, 0xe10e, 0xe10f, 23 | 0xe110, 0xe111, 0xe112, 0xe113, 0xe114, 0xe115, 0xe116, 0xe117, 0xe118, 24 | 0xe119, 0xe11a, 0xe11b, 0xe11c, 0xe11d, 0xe11e, 0xe11f, 0xe120, 0xe121, 25 | 0xe122, 0xe123, 0xe124, 0xe125, 0xe126, 0xe127, 0xe128, 0xe129, 0xe12a, 26 | 0xe12b, 0xe12c, 0xe12d, 0xe12e, 0xe12f, 0xe130, 0xe131, 0xe132, 0xe133, 27 | 0xe134, 0xe135, 0xe136, 0xe137, 0xe138, 0xe139, 0xe13a, 0xe13b, 0xe13c, 28 | 0xe13d, 0xe13e, 0xe13f, 0xe140, 0xe141, 0xe142, 0xe143, 0xe144, 0xe145, 29 | 0xe146, 0xe147, 0xe148, 0xe149, 0xe14a, 0xe14b, 0xe14c, 0xe14d, 0xe14e, 30 | 0xe14f, 0xe150, 0xe151, 0xe152, 0xe153, 0xe154, 0xe155, 0xe156, 0xe157, 31 | 0xe158, 0xe159, 0xe15a, 0xe201, 0xe202, 0xe203, 0xe204, 0xe205, 0xe206, 32 | 0xe207, 0xe208, 0xe209, 0xe20a, 0xe20b, 0xe20c, 0xe20d, 0xe20e, 0xe20f, 33 | 0xe210, 0xe211, 0xe212, 0xe213, 0xe214, 0xe215, 0xe216, 0xe217, 0xe218, 34 | 0xe219, 0xe21a, 0xe21b, 0xe21c, 0xe21d, 0xe21e, 0xe21f, 0xe220, 0xe221, 35 | 0xe222, 0xe223, 0xe224, 0xe225, 0xe226, 0xe227, 0xe228, 0xe229, 0xe22a, 36 | 0xe22b, 0xe22c, 0xe22d, 0xe22e, 0xe22f, 0xe230, 0xe231, 0xe232, 0xe233, 37 | 0xe234, 0xe235, 0xe236, 0xe237, 0xe238, 0xe239, 0xe23a, 0xe23b, 0xe23c, 38 | 0xe23d, 0xe23e, 0xe23f, 0xe240, 0xe241, 0xe242, 0xe243, 0xe244, 0xe245, 39 | 0xe246, 0xe247, 0xe248, 0xe249, 0xe24a, 0xe24b, 0xe24c, 0xe24d, 0xe24e, 40 | 0xe24f, 0xe250, 0xe251, 0xe252, 0xe253, 0xe301, 0xe302, 0xe303, 0xe304, 41 | 0xe305, 0xe306, 0xe307, 0xe308, 0xe309, 0xe30a, 0xe30b, 0xe30c, 0xe30d, 42 | 0xe30e, 0xe30f, 0xe310, 0xe311, 0xe312, 0xe313, 0xe314, 0xe315, 0xe316, 43 | 0xe317, 0xe318, 0xe319, 0xe31a, 0xe31b, 0xe31c, 0xe31d, 0xe31e, 0xe31f, 44 | 0xe320, 0xe321, 0xe322, 0xe323, 0xe324, 0xe325, 0xe326, 0xe327, 0xe328, 45 | 0xe329, 0xe32a, 0xe32b, 0xe32c, 0xe32d, 0xe32e, 0xe32f, 0xe330, 0xe331, 46 | 0xe332, 0xe333, 0xe334, 0xe335, 0xe336, 0xe337, 0xe338, 0xe339, 0xe33a, 47 | 0xe33b, 0xe33c, 0xe33d, 0xe33e, 0xe33f, 0xe340, 0xe341, 0xe342, 0xe343, 48 | 0xe344, 0xe345, 0xe346, 0xe347, 0xe348, 0xe349, 0xe34a, 0xe34b, 0xe34c, 49 | 0xe34d, 0xe401, 0xe402, 0xe403, 0xe404, 0xe405, 0xe406, 0xe407, 0xe408, 50 | 0xe409, 0xe40a, 0xe40b, 0xe40c, 0xe40d, 0xe40e, 0xe40f, 0xe410, 0xe411, 51 | 0xe412, 0xe413, 0xe414, 0xe415, 0xe416, 0xe417, 0xe418, 0xe419, 0xe41a, 52 | 0xe41b, 0xe41c, 0xe41d, 0xe41e, 0xe41f, 0xe420, 0xe421, 0xe422, 0xe423, 53 | 0xe424, 0xe425, 0xe426, 0xe427, 0xe428, 0xe429, 0xe42a, 0xe42b, 0xe42c, 54 | 0xe42d, 0xe42e, 0xe42f, 0xe430, 0xe431, 0xe432, 0xe433, 0xe434, 0xe435, 55 | 0xe436, 0xe437, 0xe438, 0xe439, 0xe43a, 0xe43b, 0xe43c, 0xe43d, 0xe43e, 56 | 0xe43f, 0xe440, 0xe441, 0xe442, 0xe443, 0xe444, 0xe445, 0xe446, 0xe447, 57 | 0xe448, 0xe449, 0xe44a, 0xe44b, 0xe44c, 0xe501, 0xe502, 0xe503, 0xe504, 58 | 0xe505, 0xe506, 0xe507, 0xe508, 0xe509, 0xe50b, 0xe50c, 0xe50d, 0xe50e, 59 | 0xe50f, 0xe510, 0xe511, 0xe512, 0xe513, 0xe514, 0xe515, 0xe516, 0xe517, 60 | 0xe518, 0xe519, 0xe51a, 0xe51b, 0xe51c, 0xe51d, 0xe51e, 0xe51f, 0xe520, 61 | 0xe521, 0xe522, 0xe523, 0xe524, 0xe525, 0xe526, 0xe527, 0xe528, 0xe529, 62 | 0xe52a, 0xe52b, 0xe52c, 0xe52d, 0xe52e, 0xe52f, 0xe530, 0xe531, 0xe532, 63 | 0xe533, 0xe534, 0xe535, 0xe536, 0xe537, 0xff5e, 0xffe5 }; 64 | 65 | private static final Set EMOJI_SET = Sets 66 | .newLinkedHashSetWithExpectedSize(EMOJI_SOFTBANK_TABLE.length); 67 | 68 | static { 69 | for (int i = 0; i < EMOJI_SOFTBANK_TABLE.length; i++) { 70 | EMOJI_SET.add(EMOJI_SOFTBANK_TABLE[i]); 71 | } 72 | } 73 | 74 | public static String allSbEmojis() { 75 | return Joiner.on(" ").join(EMOJI_SET); 76 | } 77 | 78 | public static boolean isSbEmoji(char c) { 79 | return EMOJI_SET.contains(c); 80 | } 81 | 82 | public static boolean containsSbEmoji(String s) { 83 | for (int i = 0; i < s.length(); i++) { 84 | if (isSbEmoji(s.charAt(i))) { 85 | return true; 86 | } 87 | } 88 | 89 | return false; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/com/github/binarywang/java/emoji/EmojiConverterTest.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.java.emoji; 2 | 3 | import org.apache.log4j.BasicConfigurator; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.testng.annotations.*; 7 | 8 | import static org.testng.Assert.*; 9 | 10 | public class EmojiConverterTest { 11 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 12 | 13 | private final EmojiConverter emojiConverter = EmojiConverter.getInstance(); 14 | 15 | @BeforeTest 16 | public void init(){ 17 | BasicConfigurator.configure(); 18 | } 19 | 20 | @Test 21 | public void testToAlias() { 22 | String str = "  An 😃😀awesome 😃😃string with a few 😃😉emojis!"; 23 | String alias = this.emojiConverter.toAlias(str); 24 | this.logger.info(str); 25 | this.logger.info("EmojiConverterTest.testToAlias()=====>"); 26 | this.logger.info(alias); 27 | assertEquals( 28 | ":no_good: :ok_woman: :couple_with_heart:An :smiley::grinning:awesome :smiley::smiley:string with a few :smiley::wink:emojis!", 29 | alias); 30 | } 31 | 32 | @Test 33 | public void testToHtml() { 34 | String str = "  An 😀😃awesome 😃😃string with a few 😉😃emojis!"; 35 | String result = this.emojiConverter.toHtml(str); 36 | this.logger.info(str); 37 | this.logger.info("EmojiConverterTest.testToHtml()=====>"); 38 | this.logger.info(result); 39 | assertEquals( 40 | "🙅 🙆 💑An 😀😃awesome 😃😃string with a few 😉😃emojis!", 41 | result); 42 | } 43 | 44 | @Test 45 | public void testToUnicode() { 46 | String str = "   :smiley: :grinning: :wink:"; 47 | String result = this.emojiConverter.toUnicode(str); 48 | this.logger.info(str); 49 | this.logger.info("EmojiConverterTest.testToUnicode()=====>"); 50 | this.logger.info(result); 51 | assertEquals("🙅 🙆 💑 😃 😀 😉", result); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/github/binarywang/java/emoji/EmojiReaderTest.java: -------------------------------------------------------------------------------- 1 | package com.github.binarywang.java.emoji; 2 | 3 | import com.github.binarywang.java.emoji.model.Emoji4Unicode; 4 | import org.apache.commons.lang3.builder.ToStringBuilder; 5 | import org.apache.log4j.BasicConfigurator; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.testng.annotations.*; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | import static org.testng.AssertJUnit.*; 14 | 15 | public class EmojiReaderTest { 16 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 17 | private EmojiReader emojiReader = new EmojiReader(); 18 | 19 | @BeforeTest 20 | public void init(){ 21 | BasicConfigurator.configure(); 22 | } 23 | 24 | @Test 25 | public void testRead() { 26 | Emoji4Unicode a = this.emojiReader.read(false); 27 | this.logger.info(ToStringBuilder.reflectionToString(a)); 28 | assertNotNull(a); 29 | } 30 | 31 | @Test 32 | public void testGetSb2UnicodeMap() { 33 | Map, String> sb2UnicodeMap = this.emojiReader.getSb2UnicodeMap(); 34 | 35 | this.logger.info(sb2UnicodeMap.toString()); 36 | assertNotNull(sb2UnicodeMap); 37 | } 38 | 39 | } 40 | --------------------------------------------------------------------------------