【问题标题】:writeUTF in java.io.DataOutputStreamjava.io.DataOutputStream 中的 writeUTF
【发布时间】:2017-10-12 14:55:11
【问题描述】:

我知道带有 utf8 的符号在 Java 中需要 1-4 个字节。但是当我在java.io.DataInputStream/DataOutputStream中使用readUTF/writeUTF方法的时候,发现这个方法正好解决了一个符号需要1-3个字节的情况。

static int writeUTF(String str, DataOutput out) throws IOException {
    int strlen = str.length();
    int utflen = 0;
    int c, count = 0;

   /* use charAt instead of copying String to char array */
    for (int i = 0; i < strlen; i++) {
        c = str.charAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
            utflen++;
        } else if (c > 0x07FF) {
            utflen += 3;
        } else {
            utflen += 2;
        }
    }

    if (utflen > 65535)
        throw new UTFDataFormatException(
            "encoded string too long: " + utflen + " bytes");>

    byte[] bytearr = null;
    if (out instanceof DataOutputStream) {
        DataOutputStream dos = (DataOutputStream)out;
        if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
            dos.bytearr = new byte[(utflen*2) + 2];
        bytearr = dos.bytearr;
    } else {
        bytearr = new byte[utflen+2];
    }

    bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
    bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);

    int i=0;
    for (i=0; i<strlen; i++) {
       c = str.charAt(i);
       if (!((c >= 0x0001) && (c <= 0x007F))) break;
       bytearr[count++] = (byte) c;
    }

    for (;i < strlen; i++){
        c = str.charAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
            bytearr[count++] = (byte) c;

        } else if (c > 0x07FF) {
            bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
            bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
            bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
        } else {
            bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
            bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
        }
    }
    out.write(bytearr, 0, utflen+2);
    return utflen + 2;
}

为什么不解决一个符号需要4个字节的情况?

【问题讨论】:

  • “爱”是什么意思?起初我以为是错字,但你用了两次这个词,拼写完全一样。
  • 我的意思是解决,很抱歉我拼错了。
  • 好的,我认为可以。不幸的是,我仍然不清楚你在问什么。 “解决问题”是什么意思?
  • 这个方法中,字符c有3种情况:需要1~3bytes。但在我看来,一个utf8的字符可能需要1~4bytes来填充。为什么不考虑a字符需要 4 个字节

标签: java utf-8


【解决方案1】:

这一切都在文档中进行了解释,尽管您必须通过额外的点击。

DataOutputStream#writeUTF 的文档提到它使用“modified UTF-8 编码”。该链接在原始 JavaDocs 中(我不只是为这个答案添加它),如果你关注它,你会得到一个解释该编码的页面。请特别注意摘要底部附近的部分(在进入方法摘要部分之前):

此格式与标准 UTF-8 格式的区别如下:

...

• 仅使用 1 字节、2 字节和 3 字节格式。

所以,虽然您认为 UTF-8 最多使用 4 个字节是正确的,但writeUTF 使用了修改后的版本,其中一项修改是它只支持最多 3 个字节。

【讨论】:

  • 哦,我明白了。当我阅读原始 JavaDocs 时,我忽略了“modified UTF-8”这个词。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多