2

我在 jar 文件中将以下代码从 UTF-8 转换为 ISO-8859-1,当我在 Windows 中执行此 jar 时,我得到一个结果,而在 CentOS 中我得到另一个结果。可能有人知道为什么吗?

public static void main(String[] args) {

  try {

    String x = "Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »";

    Charset utf8charset = Charset.forName("UTF-8");
    Charset iso88591charset = Charset.forName("ISO-8859-1");

    ByteBuffer inputBuffer = ByteBuffer.wrap(x.getBytes());
    CharBuffer data = utf8charset.decode(inputBuffer);

    ByteBuffer outputBuffer = iso88591charset.encode(data);
    byte[] outputData = outputBuffer.array();

    String z = new String(outputData);

    System.out.println(z);
  }
  catch(Exception e) {
    System.out.println(e.getMessage());
  }
}

在 Windows 中,java -jar test.jar > test.txt 创建一个文件,其中包含:Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »

但在 CentOS 中我得到:�?, ä, �?, é, �?, ö, �?, ü, �?, «, »

4

3 回答 3

2

这两行

x.getBytes());

String z = new String(outputData);

是平台和默认编码特定的。


通过避免特定于平台的转换,这可以在 Windows 和 Linux 上按预期运行。

String x = "Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »";

Charset utf8charset = Charset.forName("UTF-8");
Charset iso88591charset = Charset.forName("ISO-8859-1");

ByteBuffer inputBuffer = ByteBuffer.wrap(x.getBytes(utf8charset));
CharBuffer data = utf8charset.decode(inputBuffer);

ByteBuffer outputBuffer = iso88591charset.encode(data);
byte[] outputData = outputBuffer.array();

String z = new String(outputData, iso88591charset);

System.out.println(z);

印刷

Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »
于 2012-12-11T17:02:14.133 回答
2

在考虑输出之前,您首先应该在 java 中以正确的内部表示形式获取字符串。IE应该是这样的:

z.equals("Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »") == true

上面的内容可以在没有任何输出编码问题的情况下进行验证,因为它只是打印truefalse.

在 Windows 中,您已经通过

ByteBuffer inputBuffer = ByteBuffer.wrap(x.getBytes());
CharBuffer data = utf8charset.decode(inputBuffer);

因为您需要从"Ä, ä, É, é, Ö, ö, Ãœ, ü, ß, «, »""Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »"是:

ByteBuffer inputBuffer = ByteBuffer.wrap(x.getBytes( windows1252/*explicit windows1252 works on CentOS too*/));
CharBuffer data = utf8charset.decode(inputBuffer);

在这之后,你用 ISO-8859-1 做一些事情,这是徒劳的,因为你的原始字符串中只有一半的字符可以用 ISO-8859-1 表示,更不用说你已经按照上面的方法完成了。之后可以删除代码utf8charset.decode(inputBuffer)

所以现在您的代码可能如下所示:

String x = "Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »";

Charset windows1252 = Charset.forName("Windows-1252");
Charset utf8charset = Charset.forName("UTF-8");

byte[] bytes = x.getBytes(windows1252);
String z = new String(bytes, utf8charset);

                                //Still wondering why you didn't just have this literal to begin with
                                //Check that the strings are internally equal so you know at least that
                                //the code is working

System.out.println(z.equals( "Ä, ä, É, é, Ö, ö, Ü, ü, ß, «, »")); 
System.out.println(z);
于 2012-12-11T17:07:21.930 回答
1

脑海中浮现出三种可能性:

  • 实际用于源代码的编码可能因平台而异
  • 编译器默认期望的编码可能因平台而异(您可以在命令行中指定)
  • 调用时使用的平台默认编码x.getBytes()可能因平台而异

目前尚不清楚您尝试以何种方式从 UTF-8 转换为 ISO-8859-1 - 因为您的原始数据实际上只是一个String. 您将调用的结果x.getBytes() 视为UTF-8 编码的数据,但这只是平台默认值......

同样,当你写:

String z = new String(outputData);

...这是使用平台默认编码。不要那样做。

您根本不需要字节缓冲区的东西:只需使用编码text.getBytes(encoding)和使用解码new String(data, encoding)

于 2012-12-11T17:00:30.183 回答