Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何解码表情符号不适形成的十六进制字符串,如`1f1e81f1f3`";?_Java_Unicode_Decode_Emoji - Fatal编程技术网

Java 如何解码表情符号不适形成的十六进制字符串,如`1f1e81f1f3`";?

Java 如何解码表情符号不适形成的十六进制字符串,如`1f1e81f1f3`";?,java,unicode,decode,emoji,Java,Unicode,Decode,Emoji,假设有一个十六进制的表情符号字符串,比如“1f1e81f1f3”,它是一个表情符号的代码点的不合适的十六进制字符串,应该是两个字符串,比如1f1e81f1f3 我用它来解码十六进制字符串,但显然十六进制需要输入字符串的长度是均匀的,所以我需要将十六进制字符串设置为零填充样式,如“01f1e801f1f3” 目前,我只是简单地将“1f”替换为“01f”,到目前为止还不错,但从那时起,到现在为止 简单地将“1f”替换为“01f”安全吗 如果不安全,如何安全/正确地解码这些十六进制字符串,并将其还原

假设有一个十六进制的表情符号字符串,比如“
1f1e81f1f3
”,它是一个表情符号的代码点的不合适的十六进制字符串,应该是两个字符串,比如
1f1e8
1f1f3

我用它来解码十六进制字符串,但显然十六进制需要输入字符串的长度是均匀的,所以我需要将十六进制字符串设置为零填充样式,如“0
1f1e8
0
1f1f3

目前,我只是简单地将“1f”替换为“01f”,到目前为止还不错,但从那时起,到现在为止

  • 简单地将“1f”替换为“01f”安全吗
  • 如果不安全,如何安全/正确地解码这些十六进制字符串,并将其还原/翻译为正确的表情符号/字符序列?似乎我需要实现一个定制的UTF16BE解码器
背景
这个表情符号的十六进制字符串是从“
”字符串中剥离出来的,它是一条通过非官方HTTP API从流行IM软件中检索到的文本消息。

我最后编写了一个小函数来恢复表情符号

基本程序:

  • 创建一个指向十六进制字符串开头的指针
  • 从十六进制字符串的指针位置进行搜索,
    • 如果它以“
      1f
      ”开头,则在“
      1f
      ”之前填入三个零,将其存储到新的十六进制字符串中,然后将指针移到下一个第5位。否则,不进行零填充,将子字符串存储到新的十六进制字符串,并将指针步移到下一个第四位置
    • 将新的十六进制字符串解码为字节数组
    • 使用字节数组中的UTF_32BE或UTF_16BE字符编码创建新字符串
  • 循环到步骤2,直到十六进制字符串结束
  • 它可以工作,但并不完美,如果

    • 表情符号字符序列的一个字符位于补充字符中
    • 它的十六进制字符串不以“
      1f
      ”开头,或者它的十六进制字符串的长度不是5
    代码段:

    import java.util.*;
    import java.util.regex.*;
    
    import org.apache.commons.codec.*;
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.lang3.*;
    
    public static final Charset UTF_32BE = Charset.forName ("UTF-32BE");
    public static final String REGEXP_FindTransformedEmojiHexString = "<span class=\"emoji emoji(\\p{XDigit}+)\"></span>";
    public static final Pattern PATTERN_FindTransformedEmojiHexString = Pattern.compile (REGEXP_FindTransformedEmojiHexString, Pattern.CASE_INSENSITIVE);
    public static String RestoreEmojiCharacters (String sContent)
    {
            bMatched = true;
            String sEmojiHexString = matcher.group(1);
    
            Hex hex = new Hex (StandardCharsets.ISO_8859_1);
            try
            {
                for (int i=0; i<sEmojiHexString.length ();)
                {
                    String sEmoji = null;
                    Charset charset = null;
                    String sSingleEmojiGlyphHexString = null;
                    String sStartString = StringUtils.substring (sEmojiHexString, i, i+2);
                    if (StringUtils.startsWithIgnoreCase (sStartString, "1f"))
                    {
                        sSingleEmojiGlyphHexString = "000" + StringUtils.substring (sEmojiHexString, i, i+5);
                        i += 5;
                        charset = UTF_32BE;
                    }
                    else
                    {
                        sSingleEmojiGlyphHexString = StringUtils.substring (sEmojiHexString, i, i+4);
                        i += 4;
                        charset = StandardCharsets.UTF_16BE;
                    }
                    byte[] arrayEmoji = null;
                    arrayEmoji = (byte[])hex.decode (sSingleEmojiGlyphHexString);
                    sEmoji = new String (arrayEmoji, charset);
                    matcher.appendReplacement (sbReplace, sEmoji);
                }
            }
            catch (DecoderException e)
            {
                e.printStackTrace();
            }
        }
        matcher.appendTail (sbReplace);
    
        if (bMatched)
            sContent = sbReplace.toString ();
    
        return sContent;
    }
    
    import java.util.*;
    导入java.util.regex.*;
    导入org.apache.commons.codec.*;
    导入org.apache.commons.codec.binary.Hex;
    导入org.apache.commons.lang3.*;
    公共静态最终字符集UTF_32BE=Charset.forName(“UTF-32BE”);
    公共静态最终字符串REGEXP_findttransformedemojihexstring=“”;
    公共静态最终模式Pattern\u findttransformedemojihexstring=Pattern.compile(REGEXP\u findttransformedemojihexstring,Pattern.CASE\u不区分大小写);
    公共静态字符串RestoreEmojiCharacters(字符串内容)
    {
    b匹配=真;
    String sEmojiHexString=matcher.group(1);
    十六进制=新十六进制(标准字符集ISO_8859_1);
    尝试
    {
    
    对于(inti=0;ii),我最终编写了一个小函数来恢复表情符号

    基本程序:

  • 创建一个指向十六进制字符串开头的指针
  • 从十六进制字符串的指针位置进行搜索,
    • 如果它以“
      1f
      ”开头,则在“
      1f
      ”之前填充三个零,将其存储到一个新的十六进制字符串,然后指针步进到下一个第5位。否则,不进行零填充,将子字符串存储到一个新的十六进制字符串,并将指针步进到下一个第4位
    • 将新的十六进制字符串解码为字节数组
    • 使用字节数组中的UTF_32BE或UTF_16BE字符编码创建新字符串
  • 循环到步骤2,直到十六进制字符串结束
  • 它可以工作,但并不完美,如果

    • 表情符号字符序列的一个字符位于补充字符中
    • 它的十六进制字符串不以“
      1f
      ”开头,或者它的十六进制字符串的长度不是5
    代码段:

    import java.util.*;
    import java.util.regex.*;
    
    import org.apache.commons.codec.*;
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.lang3.*;
    
    public static final Charset UTF_32BE = Charset.forName ("UTF-32BE");
    public static final String REGEXP_FindTransformedEmojiHexString = "<span class=\"emoji emoji(\\p{XDigit}+)\"></span>";
    public static final Pattern PATTERN_FindTransformedEmojiHexString = Pattern.compile (REGEXP_FindTransformedEmojiHexString, Pattern.CASE_INSENSITIVE);
    public static String RestoreEmojiCharacters (String sContent)
    {
            bMatched = true;
            String sEmojiHexString = matcher.group(1);
    
            Hex hex = new Hex (StandardCharsets.ISO_8859_1);
            try
            {
                for (int i=0; i<sEmojiHexString.length ();)
                {
                    String sEmoji = null;
                    Charset charset = null;
                    String sSingleEmojiGlyphHexString = null;
                    String sStartString = StringUtils.substring (sEmojiHexString, i, i+2);
                    if (StringUtils.startsWithIgnoreCase (sStartString, "1f"))
                    {
                        sSingleEmojiGlyphHexString = "000" + StringUtils.substring (sEmojiHexString, i, i+5);
                        i += 5;
                        charset = UTF_32BE;
                    }
                    else
                    {
                        sSingleEmojiGlyphHexString = StringUtils.substring (sEmojiHexString, i, i+4);
                        i += 4;
                        charset = StandardCharsets.UTF_16BE;
                    }
                    byte[] arrayEmoji = null;
                    arrayEmoji = (byte[])hex.decode (sSingleEmojiGlyphHexString);
                    sEmoji = new String (arrayEmoji, charset);
                    matcher.appendReplacement (sbReplace, sEmoji);
                }
            }
            catch (DecoderException e)
            {
                e.printStackTrace();
            }
        }
        matcher.appendTail (sbReplace);
    
        if (bMatched)
            sContent = sbReplace.toString ();
    
        return sContent;
    }
    
    import java.util.*;
    导入java.util.regex.*;
    导入org.apache.commons.codec.*;
    导入org.apache.commons.codec.binary.Hex;
    导入org.apache.commons.lang3.*;
    公共静态最终字符集UTF_32BE=Charset.forName(“UTF-32BE”);
    公共静态最终字符串REGEXP_findttransformedemojihexstring=“”;
    公共静态最终模式Pattern\u findttransformedemojihexstring=Pattern.compile(REGEXP\u findttransformedemojihexstring,Pattern.CASE\u不区分大小写);
    公共静态字符串RestoreEmojiCharacters(字符串内容)
    {
    b匹配=真;
    String sEmojiHexString=matcher.group(1);
    十六进制=新十六进制(标准字符集ISO_8859_1);
    尝试
    {
    
    对于(int i=0;iuh,显然它不安全,标题中的示例十六进制字符串甚至不安全,
    1f1f3
    变成
    01f01f3
    。唯一安全的方法是在相应的样式表中查找
    emojixxxxxxxxx
    类的定义。
    origin?然后,您可以得到格式良好的十六进制字符串而不是格式错误的符号。@JosefZ,不,它们没有分开,一个表情符号只使用一个
    ,相反,表情符号的所有字符序列都在
    span
    元素的
    class
    属性中以十六进制字符串表示。我使用以下正则表达式提取十六进制字符串:
    。嗯,很明显显然,这是不安全的,对于标题中的示例十六进制字符串,
    1f1f3
    变为
    01f01f3
    。唯一安全的方法是在相应的样式表中查找
    emojixxxxxxxxx
    类的定义。
    来源?然后,您可以得到格式良好的十六进制字符串而不是格式错误的符号。@JosefZ,不,它们没有分开,一个表情符号只使用一个
    ,相反,表情符号的所有字符序列都在
    span
    元素的
    class
    属性内以十六进制字符串表示。我使用以下正则表达式提取十六进制字符串: