这个错误的功能编码是否相关?

时间:2015-09-12 14:41:53

标签: android encoding textview

我已经创建了一个Android应用,实际上一切正常。

我通过websockets从服务器获取数据但在将其发送到客户端之前,它在服务器上使用GZIPOutputStream压缩,如下所示:

public class GZip {

    public static ByteBuffer compress(String msg) {
        if(msg == null || msg.length() == 0)
            return null;            
        ByteBuffer bytes = null;
        try {
            ByteArrayOutputStream obj=new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(obj);
            gzip.write(msg.getBytes("UTF-8"));
            gzip.close();
            bytes = ByteBuffer.wrap(obj.toByteArray());
        } catch(Exception e) {
            return null;
        }
        return bytes;
    }

}

在客户端(Android应用),String msg解压缩:

private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
public static String decompress(byte[] compressed) {
        String msg = null;
        try {
            final int BUFFER_SIZE = 32;
            ByteArrayInputStream is = new ByteArrayInputStream(compressed);
            GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
            StringBuilder string = new StringBuilder();
            byte[] data = new byte[BUFFER_SIZE];
            int bytesRead;
            while ((bytesRead = gis.read(data)) != -1) {
                string.append(new String(data, 0, bytesRead, UTF8_CHARSET));
            }
            gis.close();
            is.close();

            msg = string.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return msg;
    }

因此,根据我的理解,在处理非US-ASCII字符时不会产生任何问题,因为所有内容都在UTF-8中正确解码或解码。

例如,考虑包含特殊字符Eckstoß的单词ß。以下是Android应用中三个TextViews的示例,它们都显示单词Eckstoß

enter image description here

我觉得这里很奇怪的是,Exkstoß这个词的所有三个版本都是如上所述进行/解码的。但是,在一行中它显示不正确。

然而,它甚至变成(恕我直言)weireder。这实际上是一个列表视图,当(由于滚动)TextView消失并重新出现时(例如再次缩小),然后(有时)正确显示字符。

什么可能导致这个奇怪的问题?

2 个答案:

答案 0 :(得分:0)

这只是猜测。

您以32字节为单位读取解压缩的字节,然后使用此代码段从字节转换为utf8字符:

new String(data, 0, bytesRead, UTF8_CHARSET)

问题可能是data中的32个字节与字符边界不对齐吗?即特殊字符用两个或多个字节编码,但不是最后一个字符的所有字节都在data缓冲区中。

这个理论并没有解释为什么滚动会给你不同的结果。

答案 1 :(得分:0)

当以UTF-8编码unicode字符时,结果字节数为1,2,3或4.例如,当日语字符U+3042以UTF-8编码时,结果字节为3(0xE3,0x81,0x82)。另一个例子是U+20BB7。当以UTF-8编码时,此unicode字符将转换为4个字节(0xF0,0xA0,0xAE,0xB7)。

假设gis.read(data)正在尝试读取[0xF0,0xA0,0xAE,0xB7](=其unicode标量值为U + 20BB7)。是否有gis.read(data)始终返回4的保证?例如,如果它返回2,则new String(data, 0, 2, UTF_8_CHARSET)无法将给定的字节数组解析为有效的UTF-8序列。