Java字符串编码 - Linux与Windows不同

4

我创建了一个Java程序(REST)服务。整个开发/测试都是在Windows上完成的,现在正在进行生产测试的部署过程。然而,出现了“小”的编码问题:

String s3 = new String("grün".getBytes(), "UTF-8");
logger.info(s3);
logger.info("das ist wirklich grün");
logger.info(new String("das ist wirklich grün".getBytes("UTF-8"), "UTF-8"));

我通过HTTP属性接收到一些值(Web应用程序托管在Tomcat上,在具有身份验证插件的Apache后面)。这些值像第1行中所示进行编码。(此值在Windows和Linux上均显示)。

当我将其转换为UTF-8,如第1行中所示,并将其写入日志文件(log4j),我在Windows机器上看到了“grün”一词(这是正确的)。在Linux服务器上,仍然有相同的输出。

然后我尝试直接使用Umlaute(üäö等),如第2行中所示,在Windows和Linux上,该值都被正确地写入日志文件。然后我尝试进行一些转换,如第3行中所示,但结果相同:两个操作系统都显示相同的结果。

这两台机器在Java中具有相同的Locale(Locale.getDefault())->我已经尝试过了。我无法更改值插入HTTP请求的方式!

3个回答

4

两台机器在Java中拥有相同的Locale (Locale.getDefault()) -> 我已经尝试过了。

决定字符串解码/编码时使用哪个字符集的是默认字符集,而不是默认语言环境。

检查你的Windows和Linux机器上Charset.defaultCharset().name()返回的内容。根据你报告的症状,我预计它们会不同。


是的,谢谢,那个提示指向了正确的方向。Windows机器使用windows-1252,而Linux使用UTF-8。 - karlis
1
使用String s3 = new String("grün".getBytes("windows-1252"), "UTF-8"); 就可以解决问题,现在在Linux机器上也是正确的。然而,我不知道为什么在Linux上要使用Windows字符集,也许这个字符串最初是在Windows机器上创建的... - karlis
可能是的!也许这个字符串最初是在Windows机器上创建的。 - Stephen C
@karlis:window1252非常接近于Latin1或iso-8859-1。这种编码已经成为标准已久,而且在协议不允许指定编码的情况下,例如HTTP中的GET请求参数,默认情况下仍然经常使用。实际上的标准变化缓慢... - Serge Ballesta

1

像这样的内容是无效的:

String s3 = new String("grün".getBytes(), "UTF-8");

这里发生了什么:您使用系统的默认字符编码(因为在调用 getBytes() 时未指定编码)获取字符串 "grün" 的字节,然后将这些字节转换回一个字符串,指定这些字节是 UTF-8 编码的文本:
字符 => 字节(使用默认字符编码,可能不是 UTF-8) => 转换回字符,就好像这些字节是 UTF-8 编码的文本
这只有当系统的默认字符编码是 UTF-8 时才能正确工作。在 Windows 上它不是(可能是 Windows-1252)。

字符串本身没有字符编码。不存在“UTF-8字符串”或“将字符串从X转换为UTF-8”的概念。字符编码指定了如何将字符串中的字符转换为字节,反之亦然,但它不是字符串本身的属性。您可以有一个字节数组,它表示用特定字符编码编码的文本。(就像“十进制”和“十六进制”不是数字本身的属性,只是您展示数字的方式)。

不要以依赖于运行系统的默认字符编码的方式编写程序;这意味着,不要在未指定字符编码的情况下调用getBytes()来处理String,例如(还有其他API调用,如果您不指定,则使用默认编码)。


谢谢!你是正确的,它不应该那样使用。然而,在找到真正的问题和解决方案后,总是可以进行改进。 - karlis
是的,所以解决方案是:检查您的程序是否依赖于默认字符编码,并修复这些地方,使其不再依赖。 - Jesper
这是我唯一需要使用类似这样的东西的部分。感谢您的答案,现在它已经实现了应有的功能。 - karlis
我只能标记一个答案为正确的。 :) 但是两个答案都帮助我找到了解决方案! - karlis

0
请比较两个环境中的JVM版本。这很可能与编码相关的问题有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接