以下代码片段适用于我的 Linux 桌面:
public static void main(String[] args) throws IOException {
byte[] bytes = new byte[] { -61, -77 };
String string = new String(bytes, StandardCharsets.UTF_8);
store(bytes, "/tmp/bytes");
store(string.getBytes(StandardCharsets.UTF_8), "/tmp/string");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(bytes);
String other = baos.toString(StandardCharsets.UTF_8.name());
store(other.getBytes(StandardCharsets.UTF_8), "/tmp/other");
checkResult(string);
checkResult(other);
}
private static void store(byte[] bytes, String path) throws IOException, FileNotFoundException {
try (FileOutputStream os = new FileOutputStream(new File(path))) {
os.write(bytes);
}
}
private static void checkResult(String string) throws Error {
System.out.println(string);
if (!string.equals("ó")) {
throw new Error("invalid: " + string);
}
}
它创建3个文件,每个文件包含一个ó。它还打印 ó 两次。但是,当我在服务器 VM 上运行此代码时。然后控制台显示?
符号而不是ó
。
3.13.0-116-generic #163~precise1-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux
$ java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-3~12.04-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)
像这样运行示例代码段可以解决控制台问题:
java -Dfile.encoding=UTF-8 -jar weird.jar
实际的tomcat应用程序调用javamail,它发送带有?
符号的电子邮件。我可以通过在JAVA_OPTS中设置以下属性来解决所有问题:-Dfile.encoding=UTF-8
但是,我在某处读到我永远不应该碰这个属性,因为它会以奇怪的方式破坏依赖项。
我现在工作。剩下的唯一问题是是否有一种更可接受的方法来做到这一点(而不会有依赖关系中断的风险(。
调用String.getBytes()
几乎从来都不是一个好主意。
总是在Charset
中通过. 通常,最好写
import static java.nio.charset.StandardCharsets.UTF_8;
...
string.getBytes(UTF_8);
在您的情况下,getBytes
很可能正在尝试使用 UTF-8 以外的其他字符集,这导致了恶作剧。