【问题标题】:Java modified UTF-8 strings in PythonJava 在 Python 中修改了 UTF-8 字符串
【发布时间】:2009-09-08 09:40:02
【问题描述】:

我正在通过 Python 与 Java 应用程序交互。我需要能够构造包含 UTF-8 字符串的字节序列。 Java 在DataInputStream.readUTF() 中使用修改后的 UTF-8 编码,Python 不支持 (yet at least)

谁能指出我在 Python 中构造 Java 修改的 UTF-8 字符串的正确方向?

更新 #1:要了解更多关于 Java 修改的 UTF-8 的信息,请查看第 550 行的 DataInput 接口中的 readUTF() 方法herehere in the Java SE docs

更新 #2:我正在尝试与第三方 JBoss Web 应用程序交互,该应用程序使用这种修改后的 UTF-8 格式通过调用 DataInputStream.readUTF() 来通过 POST 请求读取字符串(对于普通 Java UTF 的任何混淆,我们深表歉意-8 字符串操作)。

【问题讨论】:

  • “修改后的 UTF-8”是什么意思?据我所知,如果您要求 Java 将其编码为 UTF-8,它会使用完全标准的 UTF-8。请注意,Java 的原生字符串格式是 UTF-16。
  • 嗨,乔恩,我在 DataInput 接口中添加了一个指向 readUTF 方法的链接,其中提到了一点。我会尝试挖掘更多信息。
  • 维基百科上有一些信息:en.wikipedia.org/wiki/UTF-8#Modified_UTF-8(所以,序列化、一些 JNI 和类内字符串常量)。
  • 我建议修改 Java 应用程序以使用真正的 UTF-8。
  • 感谢 McDowell,我正在尝试与 JBoss Web 应用程序交互,该应用程序使用这种修改后的 utf8 格式通过 POST 请求读取字符串。

标签: java python utf-8


【解决方案1】:

有一个 Python 包可以处理读取和写入带有可选 C 扩展名的 MUTF-8 字符串:https://github.com/TkTech/mutf8

from mutf8 import encode_modified_utf8, decode_modified_utf8

unicode = decode_modified_utf8(byte_like_object)
bytes = encode_modified_utf8(unicode)

【讨论】:

    【解决方案2】:

    我知道这个问题很老了,但我仍然想贡献,因为我遇到了同样的问题并解决了它

    我在 openjdk 源码中找到了这个修改后的 utf8 的实现,并将其翻译成 python。这是我创建的要点的link

    【讨论】:

      【解决方案3】:

      您可以忽略Modified UTF-8 Encoding (MUTF-8) 并将其视为 UTF-8。在 Python 端,你可以这样处理,

      1. 将字符串转换为普通的 UTF-8 并将字节存储在缓冲区中。
      2. 将 2 字节缓冲区长度(而不是字符串长度)写入 big-endian 中的二进制文件。
      3. 写入整个缓冲区。

      我在 PHP 中完成了这项工作,Java 完全没有抱怨我的编码(至少在 Java 5 中)。

      MUTF-8 主要用于 JNI 和其他以 null 结尾的字符串的系统。与普通 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))
      

      【讨论】:

      • U+0000 并不是唯一的区别。对于将用 UTF-16 中的代理对表示的代码点,修改后的 UTF-8 对对的每个组件进行编码,就好像它们是单独的 UTF-8 代码点一样。这非常可怕,因为这意味着您必须从“修改后的 UTF-8”转换为 UTF-16,然后再转换回来以编码正确的代码点。
      • 我认为你不能忽视它:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 10: invalid start byte
      【解决方案4】:

      好的,如果您需要阅读 DataInput.readUTF 的格式,我怀疑您只需要将(有据可查的)格式转换为 Python。

      看起来并不难做到。在读取长度和二进制数据本身之后,我建议您使用第一遍来计算输出中有多少个 Unicode 字符,然后在第二遍中相应地构造一个字符串。在不了解 Python 的情况下,我不知道如何有效地构造字符串的来龙去脉,但鉴于链接的规范,我无法想象它会非常困难。您可能希望查看现有 UTF-8 解码器的源代码作为起点。

      【讨论】:

        【解决方案5】:

        也许这可以帮助你,虽然它看起来与你正在做的相反:

        Connecting a Java applet to a python SocketServer

        【讨论】:

          猜你喜欢
          • 2023-03-27
          • 2020-11-26
          • 2013-09-06
          • 2012-10-18
          • 2011-08-16
          • 1970-01-01
          • 2014-03-12
          • 2016-09-13
          • 1970-01-01
          相关资源
          最近更新 更多