Python中的Java修改过的UTF-8字符串

8 投票
5 回答
5170 浏览
提问于 2025-04-15 14:09

我正在通过Python与一个Java应用程序进行交互。我需要构建一些字节序列,这些序列里包含UTF-8字符串。但是,Java在DataInputStream.readUTF()中使用了一种修改过的UTF-8编码,而Python目前不支持这种编码(至少现在不支持)。

有没有人能告诉我怎么在Python中构建Java修改过的UTF-8字符串?

更新 #1:如果想了解更多关于Java修改过的UTF-8的信息,可以查看DataInput接口中的readUTF()方法,具体在第550行,链接在这里:这里,或者在Java SE文档中查看:这里

更新 #2:我正在尝试与一个第三方的JBoss网页应用程序进行交互,这个应用程序使用这种修改过的UTF-8格式通过POST请求读取字符串,调用的是DataInputStream.readUTF()(抱歉让大家对正常的Java UTF-8字符串操作产生了困惑)。

5 个回答

1

好的,如果你想了解DataInput.readUTF的格式,我觉得你可能需要把这个(文档写得很清楚的)格式转换成Python代码。

这看起来并不会特别难。你可以先读取数据的长度,然后再读取实际的二进制数据。我建议你先做一次处理,算出输出中会有多少个Unicode字符,然后在第二次处理时根据这个数量来构建字符串。虽然我对Python不太了解,不知道怎么高效地构建字符串,但根据提供的规范,我想这应该不会太复杂。你可以看看现有的UTF-8解码器的源代码,作为一个起点。

3

我知道这个问题已经很久了,但我还是想贡献一下,因为我也遇到了同样的问题并且解决了它。

我在openjdk的源代码中找到了这个修改过的utf8的实现,并把它翻译成了python。这里有一个链接,你可以查看我创建的代码片段。

4

你可以忽略修改过的UTF-8编码(MUTF-8),直接把它当作UTF-8来处理。在Python中,你可以这样做:

  1. 把字符串转换成普通的UTF-8,然后把字节存储在一个缓冲区里。
  2. 以大端格式写入这个2字节缓冲区的长度(注意不是字符串的长度)。
  3. 把整个缓冲区写入。

我在PHP中做过这个,Java也没有对我的编码提出任何问题(至少在Java 5中是这样)。

MUTF-8主要用于JNI和其他使用以空字符结尾的字符串的系统。它和普通UTF-8的唯一不同就是如何编码U+0000。普通UTF-8用1个字节编码(0x00),而MUTF-8用2个字节(0xC0 0x80)。首先,你在任何Unicode文本中都不应该有U+0000(这是一个无效的代码点)。其次,DataInputStream.readUTF()并不强制要求特定的编码,所以它可以接受这两种编码方式。

编辑:Python代码应该是这样的,

def writeUTF(data, str):
    utf8 = str.encode('utf-8')
    length = len(utf8)
    data.append(struct.pack('!H', length))
    format = '!' + str(length) + 's'
    data.append(struct.pack(format, utf8))

撰写回答