2011-05-30 182 views
6

这段代码有什么问题?我制作了ISO8859字符串。所以大部分的ÄÜÜ都是一些krypooutput。没关系。但如何将它们转换回普通字符(UTF8或其他)?将ISO8859字符串转换为UTF8? ÄÜÜ=>Ã为什么?

String s = new String("Üü?öäABC".getBytes(), "ISO-8859-15"); 

    System.out.println(s); 
    //ÃÃŒ?öÀABC => ok(?) 
    System.out.println(new String(s.getBytes(), "ISO-8859-15")); 
    //ÃÂÃÅ?öÃâ¬ABC => ok(?) 
    System.out.println(new String(s.getBytes(), "UTF-8")); 
    //ÃÃŒ?öÀABC => huh? 
+0

假设“krypooutput”表示来自加密函数的输出,为什么你试图将它转换为“普通字符”。这是不安全的,因为它会导致数据丢失。如果您需要该数据的可读形式,请使用十六进制编码或网址编码。 – 2011-05-30 10:41:32

+1

Java中没有“ISO8859 String”这样的东西。请参阅http://balusc.blogspot.com/2009/05/unicode-how-to-get-characters-right.html – axtavt 2011-05-30 10:42:09

+0

然后如何将输入字符串转换为“ÃÃŒ?â?ABC ABC”为正常? (如果我知道该字符串来自ISO8859文件)。 – Lissy 2011-05-30 10:47:52

回答

4
String s = new String("Üü?öäABC".getBytes(), "ISO-8859-15"); //bug 

所有这些代码所做的是损坏的数据。它将UTF-16数据转码为系统编码(不管是什么),并将这些字节,假装它们是有效的ISO-8859-15,并将它们转码为UTF-16。

那么如何将输入字符串转换为“ÃÃŒ?â?ABC ABC”为正常? (如果我知道该字符串来自ISO8859文件)。

执行此操作会是这样的正确方法:

byte[] iso859_15 = { (byte) 0xc3, (byte) 0xc3, (byte) 0xbc, 0x3f, 
    (byte) 0xc3, (byte) 0xb6, (byte) 0xc3, (byte) 0xa4, 0x41, 0x42, 
     0x43 }; 
String utf16 = new String(iso859_15, Charset.forName("ISO-8859-15")); 

字符串在Java中总是UTF-16。所有其他编码必须使用byte类型表示。

现在,如果您使用System.out来输出结果字符串,可能显示不正确,但这是一个不同的转码问题。例如,Windows console默认编码与系统编码不匹配。 System.out使用的编码必须与接收数据的设备的编码匹配。您还应该注意确保您的编辑器使用的编码相同,即reading your source files

要理解字符数据的处理方式因语言而异,请阅读this

+1

我不应该认为字节数组包含编码为ISO-8859-15的'?ABC?ABC',这可能不是OP要的字符串。 (字节)0xdc,(字节)0xfc,0x3f,(字节)0xf6,(字节)0xe4,0x41,0x42,0x43,0x22}编码为ISO-8859-15的'Üü?öABAB' ' – McDowell 2011-05-30 11:56:54

7

构造如new String("Üü?öäABC".getBytes(), "ISO-8859-15");几乎总是出错。

你在做什么在这里走的是一条String对象,在平台默认的编码并重新将其解释为ISO-8859-15将其转换回String得到相应的byte[]

如果平台默认的编码恰好是ISO-8859-15(或接近足以让这个特殊的String没有区别,例如ISO-8859-1),那么这是一个无操作(即它没有真正的效果)。

在所有其他情况下,它会最有可能的销毁String

如果你尝试“修理”一个String,那么你很可能为时已晚:如果你必须使用特定编码读取数据,那么你应该在哪里二进制数据被转换点使用它String数据。例如,如果您从InputStream读取,则需要将正确的编码传递给InputStreamReader的构造函数。

试图修复“事后”的问题将是

  1. 更难做,
  2. 往往不甚至有可能(因为错误的编码解码byte[]可以是破坏性操作)。
1

Java字符串在内部总是以UTF16数组的形式存储(并且在compitation之后以UTF8的形式存储在类文件中),所以不能简单地将字符串解释为字节数组。如果你想创建一个特定编码字符串的字节数组,你必须先转换成这种编码:

byte[] b = "Üü?öäABC".getBytes("ISO-8859-15"); 

System.out.println(new String(b, "ISO-8859-15")); // will be ok 
System.out.println(new String(b, "UTF-8")); // will look garbled 
6

我希望这将解决您的问题。

String readable = "äöüÄÖÜßáéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ"; 

try { 
    String unreadable = new String(readable.getBytes("UTF-8"), "ISO-8859-15"); 
    // unreadable -> äöüÃÃÃÃáéíóúÃÃÃÃÃàèìòùÃÃÃÃÃñà 
} catch (UnsupportedEncodingException e) { 
    // handle error 
} 

和:

String unreadable = "äöüÃÃÃÃáéíóúÃÃÃÃÃàèìòùÃÃÃÃÃñÃ"; 

try { 
    String readable = new String(unreadable.getBytes("ISO-8859-15"), "UTF-8"); 
    // readable -> äöüÄÖÜßáéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ 
} catch (UnsupportedEncodingException e) { 
    // ... 
} 
+0

嗨Jooce,我试了一样,似乎它工作正常,谢谢你这个 – Sundhar 2013-04-15 15:52:49

0

我想提供扩展的字符集,以从ISO-8859-1验证转换字符串插入UTF-8。

@Test 
public void testEnc() throws UnsupportedEncodingException { 
    String isoString = "äö"; 
    String utfString = new String(isoString.getBytes("ISO-8859-1"), "utf-8"); 
    boolean validConvertion = containsSpecialCharacter(utfString); 
    assertTrue(validConvertion); 
} 

public boolean containsSpecialCharacter(String str) { 
    String[] readable = new String[] { "Ã", "Ã", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ã", "Þ", "ß", 
      "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", 
      "÷", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ" }; 
    for (String st : readable) { 
     if (str.contains(st)) { 
      return true; 
     } 
    } 
    return false; 
} 
2

这里是一个字符串输出一个简单的方法(我创建了一个方法来做到这一点):

public static String (String input){ 
String output = ""; 
try { 
    /* From ISO-8859-1 to UTF-8 */ 
    output = new String(input.getBytes("ISO-8859-1"), "UTF-8"); 
    /* From UTF-8 to ISO-8859-1 */ 
    output = new String(input.getBytes("UTF-8"), "ISO-8859-1"); 
} catch (UnsupportedEncodingException e) { 
    e.printStackTrace(); 
} 
return output; 

}

// Example 
input = "Música"; 
output = "Música"; 

它的作品! :)