Java 为什么String.getBytes()在编译的jar中表现不同?

Java 为什么String.getBytes()在编译的jar中表现不同?,java,encoding,Java,Encoding,我有一个项目,它从一个用拉丁语编码的明文文件中读取数据,然后用UTF-8编码将其发送到MySQL数据库。 在早期版本的一些旧代码中,使用新字符串(String.getBytes(“UTF-8”))手动重新编码文件中已正确读取的字符串。这在Eclipse中工作得很好,但由于某种原因,在将其编译为可执行文件.jar后,这导致字符串以拉丁1编码发送,尽管显式地将JDBC定义为UTF-8编码。 除去不必要的转换后,它在IDE和编译的jar中都能正常工作 我想知道这可能是什么原因造成的。jar和IDE是在

我有一个项目,它从一个用拉丁语编码的明文文件中读取数据,然后用UTF-8编码将其发送到MySQL数据库。 在早期版本的一些旧代码中,使用
新字符串(String.getBytes(“UTF-8”))
手动重新编码文件中已正确读取的字符串。这在Eclipse中工作得很好,但由于某种原因,在将其编译为可执行文件.jar后,这导致字符串以拉丁1编码发送,尽管显式地将JDBC定义为UTF-8编码。 除去不必要的转换后,它在IDE和编译的jar中都能正常工作

我想知道这可能是什么原因造成的。jar和IDE是在同一个系统上执行的,除非Eclipse添加一些设置,否则我不知道VM设置是相同的。此行为在其他机器上也以完全相同的方式可见。

有两个问题:

new String(String.getBytes("UTF-8"))
采用默认系统编码来创建新字符串。例如,您应该始终明确指定新字符串的编码

new String(String.getBytes("UTF-8"), "UTF-8")
另一个系统上的默认编码很可能不同,导致字符集转换(例如从UTF-8到Cp1252)

仅当字符串读取错误且目标字符集与源字符集不同时,应用的转换才相关。例如:您最初将一些字节读取为Cp1252,但随后需要将其转换为另一个字符集(例如Cp1250)。然后你会做:

new String(String.getBytes("Cp1252"), "Cp1250")
这将在Cp1252中将字符串中的字符转换为字节,然后获取字节并在Cp1250中解释它们。对于某些(但不是全部)字符,这将映射到相同的字符,但其他字符将被重新映射

如果字符串已经按照您在问题中的暗示正确读取,那么这样做是完全没有意义的。Java中的字符串在内部只是一个字符数组,只有当作为字节数据持久化(或从字节数据读取)时编码才相关。

这一行:

new String(String.getBytes("UTF-8"))
没有实现任何类型的重新编码。它所做的是将一个字符串转换成一个字节数组,使用UTF-8编码,然后使用默认编码从中构造一个新字符串。结果还是一个字符串,Java中的字符串没有相关的编码:根据规范,它们包含
char
s,即UTF-16码点。没有定义字节级编码。这行代码所能做的最好的事情就是检索完全相同的字符串,如果默认编码不匹配,结果将是一个断开的字符串


如果对数据库使用了错误的编码,则必须在JDBC级别采取行动,确保通过线路发送的字符串正确编码。

您是否尝试直接检索
字符集
或验证
字符集.isSupported(“UTF-8”)
?@Jack如果输出中除了非标准字符外,字符串仍然正确,这真的会成为问题吗?IDE或.jar中也没有与此相关的异常。我只是使用了
getBytes(“UTF-8”)
与此完全相同,并且包含了
不支持的编码异常的异常处理
。所有Java实现都需要支持UTF-8这是对这个问题的一个很好的解释:)我只能假设转换在过去的某个时候是必要的,只是在我删除它之前随着代码的发展而保留下来。