解码和编码字符串,ISO-8859-1 到 Java 中的 UTF-8
decoding and encoding strings, ISO-8859-1 to UTF-8 in Java
我已经阅读了有关此问题的其他帖子,但他们提供的解决方案对我不起作用。实际上,官方 Java 文档也没有按预期工作(我正在使用 Java 11):https://docs.oracle.com/javase/tutorial/i18n/text/string.html
我的问题是我一次从字节缓冲区读取一个字节,将其放入一个字节数组,然后从该字节数组中生成一个字符串。我读取的字节来自一个只能发送 ISO-8859-1 字节的嵌入式系统,所以我最终得到一个带有 ISO-8859-1 字节的字节数组,我最终得到的 Java 字符串因此是 ISO -8859-1 编码。这里没问题。 IntelliJ 中的字符串如下所示:
我试图从 ISO-8859-1 转换为 UTF-8 的字节是黄色的。我希望它们是 UTF-8,所以最后“C9”字节应该被“C3A9”字节替换。
第一步工作正常,我这样做:maintenanceResponseString.getBytes(StandardCharsets.UTF_8)
我得到了我想要的正确字节,字符串的 UTF-8 编码,那是好:
问题就出在这里,当我尝试用这些新的(和好的)字节制作一个字符串时,像这样:
new String(maintenanceResponseString.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)
旧字节又回来了 ?!!这就像“getBytes(UTF-8)”从未真正发生过。这不是文档所说的应该发生的事情......我在这里错过了什么?我做了测试,字符串确实仍然是 ISO-8859-1 编码的……我不知道这里发生了什么。来自“getBytes”的字节在哪里?
如何将包含 ISO-8859-1 字节的字符串转换为 UTF-8 字节?我没有其他选择,我需要为专业项目把它做得非常糟糕......这应该很容易!
注意:我已经尝试过
等替代方案
ByteBuffer buffer = StandardCharsets.UTF_8.encode(s);
return StandardCharsets.UTF_8.decode(buffer).toString();
但同样的事情发生了。
预先感谢您的帮助。
编辑:
关于 Java 9+ 中的字符串如何在内部不再仅表示为 UTF-16,而是 Latin-1(为什么...)的评论中的一些信息,我认为这就是让我认为字符串是“在 Latin-1 中内部编码”当它只是字符串的默认表示时 如果我们没有指定我们在显示字符串时要使用的编码。
根据我现在的理解,字符串本身未绑定任何编码,您可以在写入时选择要显示的编码。
实际上,我的问题是字符串最终通过 LATIN-1 中的 JAXB 编组写入 XML 文件,我现在认为问题就在那里……当我再次访问我的工作计算机时,我会进一步挖掘并在这里报告
事实证明,字符串和“它们的编码”没有任何问题。发生的事情是我真的很困惑,因为调试器以“默认内部存储编码”显示字符串的内容,即 ISO-8859-1(但可以是 UTF-16,取决于字符串的内容)。
引自 JEP-254 :
We propose to change the internal representation of the String class
from a UTF-16 char array to a byte array plus an encoding-flag field.
The new String class will store characters encoded either as
ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes
per character), based upon the contents of the string. The encoding
flag will indicate which encoding is used.
但实际上内部编码存储并不重要。当需要写入时,字符串 将在写入时使用您想要的任何编码。
我的问题实际上是当我使用 Spring RestTemplate 在 HTTP 请求中发送字符串时。我没有 header 指定要在请求中使用的“字符集”,如果没有另外说明,RestTemplate 默认为 ISO-8859-1。我添加了charset=utf-8,请求中的String正确写成了UTF-8。
感谢@VGR @Eugene @skomisa 的帮助
我已经阅读了有关此问题的其他帖子,但他们提供的解决方案对我不起作用。实际上,官方 Java 文档也没有按预期工作(我正在使用 Java 11):https://docs.oracle.com/javase/tutorial/i18n/text/string.html
我的问题是我一次从字节缓冲区读取一个字节,将其放入一个字节数组,然后从该字节数组中生成一个字符串。我读取的字节来自一个只能发送 ISO-8859-1 字节的嵌入式系统,所以我最终得到一个带有 ISO-8859-1 字节的字节数组,我最终得到的 Java 字符串因此是 ISO -8859-1 编码。这里没问题。 IntelliJ 中的字符串如下所示:
我试图从 ISO-8859-1 转换为 UTF-8 的字节是黄色的。我希望它们是 UTF-8,所以最后“C9”字节应该被“C3A9”字节替换。
第一步工作正常,我这样做:maintenanceResponseString.getBytes(StandardCharsets.UTF_8)
我得到了我想要的正确字节,字符串的 UTF-8 编码,那是好:
问题就出在这里,当我尝试用这些新的(和好的)字节制作一个字符串时,像这样:
new String(maintenanceResponseString.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)
旧字节又回来了 ?!!这就像“getBytes(UTF-8)”从未真正发生过。这不是文档所说的应该发生的事情......我在这里错过了什么?我做了测试,字符串确实仍然是 ISO-8859-1 编码的……我不知道这里发生了什么。来自“getBytes”的字节在哪里?
如何将包含 ISO-8859-1 字节的字符串转换为 UTF-8 字节?我没有其他选择,我需要为专业项目把它做得非常糟糕......这应该很容易!
注意:我已经尝试过
等替代方案ByteBuffer buffer = StandardCharsets.UTF_8.encode(s);
return StandardCharsets.UTF_8.decode(buffer).toString();
但同样的事情发生了。
预先感谢您的帮助。
编辑: 关于 Java 9+ 中的字符串如何在内部不再仅表示为 UTF-16,而是 Latin-1(为什么...)的评论中的一些信息,我认为这就是让我认为字符串是“在 Latin-1 中内部编码”当它只是字符串的默认表示时 如果我们没有指定我们在显示字符串时要使用的编码。
根据我现在的理解,字符串本身未绑定任何编码,您可以在写入时选择要显示的编码。 实际上,我的问题是字符串最终通过 LATIN-1 中的 JAXB 编组写入 XML 文件,我现在认为问题就在那里……当我再次访问我的工作计算机时,我会进一步挖掘并在这里报告
事实证明,字符串和“它们的编码”没有任何问题。发生的事情是我真的很困惑,因为调试器以“默认内部存储编码”显示字符串的内容,即 ISO-8859-1(但可以是 UTF-16,取决于字符串的内容)。
引自 JEP-254 :
We propose to change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field. The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.
但实际上内部编码存储并不重要。当需要写入时,字符串 将在写入时使用您想要的任何编码。
我的问题实际上是当我使用 Spring RestTemplate 在 HTTP 请求中发送字符串时。我没有 header 指定要在请求中使用的“字符集”,如果没有另外说明,RestTemplate 默认为 ISO-8859-1。我添加了charset=utf-8,请求中的String正确写成了UTF-8。
感谢@VGR @Eugene @skomisa 的帮助