为什么可以';我在Java中的字符数组中存储日文UTF-8字符吗?

为什么可以';我在Java中的字符数组中存储日文UTF-8字符吗?,java,string,unicode,utf-8,Java,String,Unicode,Utf 8,我有一个字符串“1234567(Asics(アシックスワーキング) )". 它有unicode字符,有些是ASCII的一部分,有些不是。java所做的是,它用一个字节表示ASCII字符,用两个字节表示其他unicode字符 我的程序的某些部分无法处理这种格式的字符串,所以我想把这些值编码成转义序列 那么绳子呢 “1234567(Asics(アシックスワーキング) )" 将映射到 “\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0028\u0041\u00

我有一个字符串“1234567(Asics(アシックスワーキング) )". 它有unicode字符,有些是ASCII的一部分,有些不是。java所做的是,它用一个字节表示ASCII字符,用两个字节表示其他unicode字符

我的程序的某些部分无法处理这种格式的字符串,所以我想把这些值编码成转义序列

那么绳子呢

“1234567(Asics(アシックスワーキング) )"

将映射到

“\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0028\u0041\u0073\u0069\u0063\u0073\u0020\u0028\u30a2\u30b7\u30c3\u30af\u30b9\u30ef\u30fc\u30ad\u30f3\u30b0\u0029\u0029\u0020\u0029”

我编写此函数就是为了做到这一点:-

public static String convertToEscaped(String utf8) throws java.lang.Exception
    {
    char[] str = utf8.toCharArray();
    StringBuilder unicodeStringBuilder = new StringBuilder();
    for(int i = 0; i < str.length; i++){
    char charValue = str[i];
    int intValue = (int) charValue;
    String hexValue = Integer.toHexString(intValue);
    unicodeStringBuilder.append("\\u");
    for (int length = hexValue.length(); length < 4; length++) {
        unicodeStringBuilder.append("0");
    }
    unicodeStringBuilder.append(hexValue);
    }
    return unicodeStringBuilder.toString();
    }
输出: \u3132\u3334\u3536\u3738\u2841\u7369\u6373\u2028\uffffe282\uffffa1e3\uffff81b7\uffffe283\uffff82e3\uffff81af\uffffe282\uffffb8e3\uffff82af\uffffe283\uffffbbe3\uffff81ad\uffffe283\uffff81b0\U292


但这也是错误的,因为我正在将两个单字节字符合并为一个。我能做些什么来克服这个问题?

正如他们在上面所评论的,java中字符串的内部表示是utf-16。找到了吗

Character.codePointAt()和Integer.toHexString()在您的案例中非常有用

将参数重命名为just theString,还从原始方法中删除了throws Exception子句,因为没有抛出异常。(通常抛出这些泛型异常是不好的做法)

public静态字符串convertToEscaped(字符串字符串){
char[]charArr=字符串toCharArray();
StringBuilder sb=新的StringBuilder();
对于(int i=0;i
我不知道其他代码的具体要求。但我的建议是不要重新发明轮子,不要使用API的内置编码功能

例如,使用
StandardCharsets.UTF_16BE
StandardCharsets.UTF_16LE
调用
getBytes
,根据所需的尾数:

String s = "1234567(Asics (アシックスワーキング) )";

byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
byte[] utf16 = s.getBytes(StandardCharsets.UTF_16BE); // high order byte first

System.out.println(s.length()); // 28
System.out.println(utf8.length); // 48
System.out.println(utf16.length); // 56 (2 bytes for each char)

“java所做的是,ASCII字符需要一个字节,其他unicode字符需要两个字节。"你这么说是什么意思?每个字符都应该用一个
char
表示,在Java中它是16位的。并非所有情况都是这样。请参阅:Java
char
s仍然使用16位Unicode。这个答案只是说a
ObjectOutputStream
在内部使用不同的编码,UTF-8可以使用超过1位的编码但是如果你在做I/O,你通常可以指定你想要的编码。那么为什么字节是[]编码出错?@jornverne是的,当你运行它时,默认值是你的默认值;当我运行它时,默认值是我的默认值。虽然这在20世纪90年代可能很有用,但现在应该是一个非常谨慎和罕见的决定,正如你指出的,这就是为什么它不适合提问者。java中字符串的内部表示是utf-16“是真的,但内部是内部,现在只有在API级别才是真的。一些实现通过内部使用时间换取空间,并在用户代码需要时转换为UTF-16。或者换句话说,Java使用UTF-16,但JVM可能不使用。我尝试了UTF-16,它也可以在外部工作()但在我的程序中,它将这些日文字符转换为4字节。不知道为什么会发生这种情况:/也许字符串是其他形式的,我只是记录下来看看里面有什么。@DhruvChandhok那你是怎么得到字符串的?我只是从你的示例中复制并粘贴了它。@DhruvChandhok确实有些字符可以占用4字节对于UTF-16,我假设您没有使用它们,因为您自己正在将每个字符转换为16位。您也可以通过
Charset.forName(“UTF-32BE”)使用UTF-32BE
,这将使所有字符都有4个字节。问题在于如何填充字符串。我尝试对上面的字符串进行了硬编码,结果成功了。不过,在打印字符串时,“1234567(Asics(アシックスワーキング) )" 是打印的,它可能是其他形式。调查它,以前从未遇到过此问题。感谢您的帮助:)
public static String convertToEscaped(String theString) {
    char[] charArr = theString.toCharArray();

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < charArr.length; i++) {
        String hexString = Integer.toHexString(Character.codePointAt(charArr, i));

        sb.append("\\u");

        if (hexString.length() == 2) {
            sb.append("00");
        }
        sb.append(hexString);
    }
    return sb.toString();
 }
String s = "1234567(Asics (アシックスワーキング) )";

byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
byte[] utf16 = s.getBytes(StandardCharsets.UTF_16BE); // high order byte first

System.out.println(s.length()); // 28
System.out.println(utf8.length); // 48
System.out.println(utf16.length); // 56 (2 bytes for each char)