【问题标题】:Convert ISO8859 String to UTF8? ÄÖÜ => ÃÃ why?将 ISO8859 字符串转换为 UTF8? ÄÖÜ => ÃÃ 为什么?
【发布时间】:2011-09-04 17:36:10
【问题描述】:

这段代码有什么问题?我制作了一个 ISO8859 字符串。所以大部分ÄÖÜ都是一些krypooutput。没关系。但是如何将它们转换回普通字符(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?

【问题讨论】:

  • 假设“krypooutput”表示来自加密函数的输出,您为什么要尝试将其转换为“普通字符”。这是不安全的,因为它会导致数据丢失。如果您需要该数据的人类可读形式,请使用 hex-encoding 或 url-encoding。
  • Java 中没有“ISO8859 字符串”之类的东西。见balusc.blogspot.com/2009/05/…
  • 那么如何将像“ÃŒ?öÀABC”这样的输入字符串转换为普通字符串? (如果我知道该字符串来自 ISO8859 文件)。
  • 那么,你有一个IOS8859文件吗?然后你需要在从中读取字符串时指定编码,例如通过InputStreamReader
  • @Lissy:您遇到的第一个严重问题是您在 .java 源文件中使用了非 ASCII 字符,这是妄想。可悲的是,Java 没有指定其源代码文件的编码,如果您在 .java 源文件中使用非 ASCII 字符,您会发现一个很痛苦的世界。字符串应该被外部化,在 .java cmets 中使用非 ASCII 字符的 Java 程序员应该被枪杀。这在玩具环境中很好,您有一个开发人员在一个操作系统上使用一个 IDE 和一个 VCS,但是一旦您混合开发人员,您就会发现痛苦。外化你的字符串。

标签: java string unicode character-encoding


【解决方案1】:

这个解决方案对我有用,希望对你有所帮助

String s1 = "l'épargne";
String s2 = new String(s1.getBytes("iso-8859-1"), "utf8");

【讨论】:

    【解决方案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";
    

    有效!! :)

    【讨论】:

      【解决方案3】:

      我想提供扩展的字符集,以验证从 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;
      }
      

      【讨论】:

        【解决方案4】:

        希望这能解决你的问题。

        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) {
            // ...
        }
        

        【讨论】:

        • 嗨 Jooce,我也试过了,看起来效果不错,谢谢
        【解决方案5】:

        Java 字符串在内部始终存储为 UTF16 数组(编译后在类文件中存储为 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】:

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

          您在这里所做的是获取String 对象,在平台默认编码 中获取相应的byte[] 并将其重新解释为ISO-8859-15 以将其转换回来到String

          如果平台默认编码恰好是 ISO-8859-15(或接近到足以对这个特定的String 没有影响,例如 ISO-8859-1),那么它是无操作(即没有实际效果)。

          在所有其他情况下,它很可能会破坏String

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

          尝试“事后”解决问题将是

          1. 更难做和
          2. 通常甚至不可能(因为使用错误编码解码 byte[] 可能是破坏性操作)。

          【讨论】:

            【解决方案7】:
            String s = new String("Üü?öäABC".getBytes(), "ISO-8859-15"); //bug
            

            这段代码所做的只是破坏数据。它将 UTF-16 数据转码为系统编码(无论是什么),然后获取这些字节,假装它们是有效的 ISO-8859-15 并将它们转码为 UTF-16。

            那么如何将“ÃÃŒ?öÀ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

            【讨论】:

            • 我不应该认为字节数组包含编码为 ISO-8859-15 的ÃÃŒ?öÀABC,这可能不是 OP 想要的字符串。 Üü?öäABC 编码为 ISO-8859-15 将是数组 { 0x22, (byte) 0xdc, (byte) 0xfc, 0x3f, (byte) 0xf6, (byte) 0xe4, 0x41, 0x42, 0x43, 0x22 }
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-29
            • 1970-01-01
            • 2010-12-04
            • 1970-01-01
            • 1970-01-01
            • 2015-09-04
            相关资源
            最近更新 更多