首页 > 解决方案 > 如何在 Java 中对字节数组中的补充 unicode 字符进行编码?

问题描述

我正在使用 将InputStream来自 TCP 服务器(用 C# 编写)的字节读取到 中byte[],并使用 将它们编码为字符串new String(byteArray, "UTF-16LE")。此方法可以很好地编码基本多语言平面中的字符,但不处理补充字符。

我知道 C# 中的字节是无符号的,而 Java 字节是有符号的,并且补充字符可以由一个或两个 unicode 值组成。

        ByteBuffer wrapped = ByteBuffer.wrap(dataBytes);
        wrapped.order(ByteOrder.LITTLE_ENDIAN);
        short noOfSites = wrapped.getShort();

        for(int i = 0; i < noOfSites; i++){
            short siteNo = wrapped.getShort();
            short textLength = wrapped.getShort();
            byte[] textBytes = new byte[textLength];
            wrapped.get(textBytes, 0, textLength);

            for(byte bite : textBytes){
                System.out.print(bite+" ");
            } //just to see what's in the byte array

            String siteText = new String(textBytes, "UTF_16LE");
            System.out.println(siteNo + ": " + siteText);
            siteList.add(new Site(siteNo, siteText));
            publishProgress(siteNo + " - " + siteText);
        }

在这种情况下,dataBytes是包含从服务器读取的字节的字节数组,noOfSites是要从服务器读取的对象数,siteNo是 ID,textLength是包含站点名称的字节数,并且textBytes是包含这些字节。

当从服务器接收到单词“MÜNSTER”时,读入缓冲区的字节是: 77 0 -3 -1 78 0 83 0 84 0 69 0 82 0. 但是,“Ü”字符无法识别,我认为这-3 -1取决于 Java 尝试(并且失败)编码的 UTF-16 值。我知道在 C# 中,“Ü”由 表示DC-00,但我不明白为什么-3 -1在 Java 中会这样。任何帮助将不胜感激。

标签: javaandroidunicodetcp

解决方案


“Û”字符未在您的源中编码 - 到达接收器端“-3,-1”的序列是-替换字符0xfffd的 UTF 16 LE 编码。

如果没有看到服务器端代码,很难知道发生了什么,但它很糟糕。utf-16 可以毫不费力地处理像“Ü”这样的字符。实际上,它甚至不在前 256 个 unicode 代码点之外,更不用说在基本多语言平面之外了。(这是一个在许多西方语言中很常见的字符,甚至是拉丁字符,它怎么可能超出设计用于容纳世界上所有语言的字符的平面?)

发生的事情是,从您的文本到用于电汇的 utf-16 的代码路径在某些时候被明确指示为任何不仅仅是 ASCII 的字符设置替换字符(旧的 unicode 代码点 0x20 -0x7f,仅包括无重音的拉丁字符)。

需要明确的是,换句话说:数据在服务器端被损坏,并且所有非 ASCII 匹配字符都可能被压缩为“替换字符”。对客户端代码的任何摆弄都无法解决这个问题。


推荐阅读