Java-使用单个表情符号读取UTF-8文件

Java-使用单个表情符号读取UTF-8文件,java,unicode,encoding,java-8,Java,Unicode,Encoding,Java 8,我有一个带有单个unicode符号的文件。 该文件以UTF-8编码。 它包含一个表示为4字节的符号。 F0 9F 98 8A 当我读文件时,我得到两个符号/字符 下面的程序打印 ? 2 ? ? 55357 56842 ====================================== �� 16 & ====================================== ? 2 ? ======================

我有一个带有单个unicode符号的文件。
该文件以UTF-8编码。
它包含一个表示为4字节的符号。

F0 9F 98 8A

当我读文件时,我得到两个符号/字符

下面的程序打印

?
2
?
?
55357
56842
======================================
��
16
&
======================================
?
2
?
======================================
这正常吗。。。还是虫子?还是我误用了什么?
如何在我的代码中获得单个表情符号

编辑:而且。。。如何将其转换为XML?

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class Test008 {

    public static void main(String[] args) throws Exception{
        BufferedReader in = new BufferedReader(
                   new InputStreamReader(
                              new FileInputStream("D:\\DATA\\test1.txt"), "UTF8"));
        
        String s = "";
        while ((s = in.readLine()) != null) {
            System.out.println(s);
            System.out.println(s.length());
            System.out.println(s.charAt(0));
            System.out.println(s.charAt(1));
            
            System.out.println((int)(s.charAt(0)));
            System.out.println((int)(s.charAt(1)));
            
            String z = org.apache.commons.lang.StringEscapeUtils.escapeXml(s);
            String z3 = org.apache.commons.lang3.StringEscapeUtils.escapeXml(s);
            
            System.out.println("======================================");
            System.out.println(z);
            System.out.println(z.length());
            System.out.println(z.charAt(0));
            
            System.out.println("======================================");
            System.out.println(z3);
            System.out.println(z3.length());
            System.out.println(z3.charAt(0));
            
            System.out.println("======================================");

        }

        in.close();
    }

}

是正常情况,Unicode符号为2个UTF-16字符(1个字符为2个字节)


评论后

Java,使用流:

public static String escapeToAsciiHTML(String s) {
    StringBuilder sb = new StringBuilder();
    s.codePoints().forEach(cp -> {
        if (cp < 128) {
            sb.append((char) cp);
        } else{
            sb.append("&#").append(cp).append(";");
        }
    });
    return sb.toString();
}
公共静态字符串EscapetoAscihTML(字符串s){
StringBuilder sb=新的StringBuilder();
s、 codePoints().forEach(cp->{
if(cp<128){
sb.追加((char)cp);
}否则{
附加(&#)附加(cp)附加(;);
}
});
使某人返回字符串();
}

是正常情况,Unicode符号为2个UTF-16字符(1个字符为2个字节)


评论后

Java,使用流:

public static String escapeToAsciiHTML(String s) {
    StringBuilder sb = new StringBuilder();
    s.codePoints().forEach(cp -> {
        if (cp < 128) {
            sb.append((char) cp);
        } else{
            sb.append("&#").append(cp).append(";");
        }
    });
    return sb.toString();
}
公共静态字符串EscapetoAscihTML(字符串s){
StringBuilder sb=新的StringBuilder();
s、 codePoints().forEach(cp->{
if(cp<128){
sb.追加((char)cp);
}否则{
附加(&#)附加(cp)附加(;);
}
});
使某人返回字符串();
}

StringEscapeUtils断开。不要用它。试试看

或者,更好的是,由于ApacheCommons库往往是糟糕的API**和坏的***无论如何,guava*

java是unicode,是的,但“char”是个谎言char'不代表字符;它表示单个无符号16位数字。例如,从
j.l.String
对象中获取字符的实际方法不是
charAt
,这是一种用词不当的方法;这是
codepoint
,还有朋友们

这(字符是伪造的)通常并不重要;大多数实际字符适合16位
char
类型。但如果他们不这样做,这很重要,而且表情符号也不合适。在java使用的unicode模型和
char
类型中,您将获得2个char值(表示单个unicode字符)。这一对被称为“代理对”

请注意,正确的方法往往适用于
int
(毕竟,您需要32位来表示一个unicode符号)

*)番石榴也有它自己的问题,因为它积极地不向后兼容自己,它往往导致依赖地狱。不幸的是,这是一个选择你的毒药的交易

**)Utils anything通常是糟糕的API设计的标志“util”作为一个术语几乎毫无意义,通常意味着您已经破坏了面向对象的模型。当然,正确的模型是使用一个对象来表示将数据以一种形式(例如,原始字符串)转换为另一种形式(例如,可以直接转储到XML文件中的字符串,经过转义)的过程,这样的对象将被称为“转义器”,并且可能存在于名为“转义器”或“文本”的包中。幸运的是,apache库以及guava的后续版本“修复”了这一问题


***)正如这个示例所示,这些API通常不做您希望它们做的事情。注意apache是开源的;如果您希望这些API更好,它们可以接受拉请求:)

StringEscapeUtils被破坏。不要用它。试试看

或者,更好的是,由于ApacheCommons库往往是糟糕的API**和坏的***无论如何,guava*

java是unicode,是的,但“char”是个谎言char'不代表字符;它表示单个无符号16位数字。例如,从
j.l.String
对象中获取字符的实际方法不是
charAt
,这是一种用词不当的方法;这是
codepoint
,还有朋友们

这(字符是伪造的)通常并不重要;大多数实际字符适合16位
char
类型。但如果他们不这样做,这很重要,而且表情符号也不合适。在java使用的unicode模型和
char
类型中,您将获得2个char值(表示单个unicode字符)。这一对被称为“代理对”

请注意,正确的方法往往适用于
int
(毕竟,您需要32位来表示一个unicode符号)

*)番石榴也有它自己的问题,因为它积极地不向后兼容自己,它往往导致依赖地狱。不幸的是,这是一个选择你的毒药的交易

**)Utils anything通常是糟糕的API设计的标志“util”作为一个术语几乎毫无意义,通常意味着您已经破坏了面向对象的模型。当然,正确的模型是使用一个对象来表示将数据以一种形式(例如,原始字符串)转换为另一种形式(例如,可以直接转储到XML文件中的字符串,经过转义)的过程,这样的对象将被称为“转义器”,并且可能存在于名为“转义器”或“文本”的包中。幸运的是,apache库以及guava的后续版本“修复”了这一问题


***)正如这个示例所示,这些API通常不做您希望它们做的事情。注意apache是开源的;如果您希望这些API更好,它们会接受拉取请求:)

字符集不应该被称为
“UTF-8”
而不是
“UTF8”
?@f1sh我认为两者都可以,但会尝试一下。。。是 啊同样,请注意,在XML中根本不需要转义这些字符,只要使用正确的编码并且接收方正确处理XML,就可以按原样编写它们。必须转义的唯一字符是XML语法本身使用的字符(甚至那些并不总是如此,例如,
@JoachimSauer谢谢……是的,这似乎就是来自Apache commons lang 3.11的
StringEscapeUtils.escapeXml10
所做的。它根本无法逃避它。我想,我现在已经让它工作了。非常感谢!这个字符集不应该被称为
“UTF-8”