2011-05-30 41 views
6

Có vấn đề với mã này? Tôi đã tạo một chuỗi ISO8859. Vì vậy, hầu hết các ÄÖÜ là một số krypooutput. Đó là tốt. Nhưng làm thế nào để chuyển đổi chúng trở lại ký tự bình thường (UTF8 hoặc một cái gì đó)?Chuyển đổi chuỗi ISO8859 thành UTF8? ÄÖÜ => ÃÃ tại sao?

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

Giả sử rằng "krypooutput" có nghĩa là đầu ra từ một hàm mã hóa, tại sao bạn đang cố chuyển đổi nó thành "ký tự bình thường". Điều đó là không an toàn, vì nó sẽ dẫn đến mất dữ liệu. Nếu bạn cần biểu mẫu có thể đọc được của con người, hãy sử dụng mã hóa hex hoặc mã hóa url. –

+1

Không có thứ như "ISO8859 String" trong Java. Xem http://balusc.blogspot.com/2009/05/unicode-how-to-get-characters-right.html – axtavt

+0

Sau đó, cách chuyển đổi chuỗi đầu vào như "ÃÃŒ? öà € ABC" thành bình thường? (nếu tôi biết rằng chuỗi là từ một tập tin ISO8859). – Lissy

Trả lời

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

Tất cả các mã này không có gì làm hỏng dữ liệu. Nó chuyển mã UTF-16 thành mã hóa hệ thống (bất kỳ cái gì) và lấy các byte đó, giả vờ chúng là hợp lệ ISO-8859-15 và chuyển mã chúng thành UTF-16.

Sau đó, cách chuyển đổi chuỗi đầu vào như "ÃÃŒ? öà € ABC" thành bình thường? (nếu tôi biết rằng chuỗi là từ một tập tin ISO8859).

Các cách chính xác để thực hiện thao tác này sẽ là như thế này:

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")); 

Strings trong Java luôn UTF-16. Tất cả các mã hóa khác phải được thể hiện bằng loại byte.

Bây giờ, nếu bạn sử dụng System.out để xuất chuỗi kết quả, có thể không xuất hiện chính xác, nhưng đó là một vấn đề chuyển mã khác. Ví dụ: mã hóa mặc định Windows console không khớp với mã hóa hệ thống. Mã hóa được sử dụng bởi System.out phải khớp với mã hóa của thiết bị nhận dữ liệu. Bạn cũng nên cẩn thận để đảm bảo rằng bạn đang sử dụng reading your source files với cùng một bộ mã hóa mà trình soạn thảo của bạn đang sử dụng.

Để hiểu cách xử lý dữ liệu ký tự khác nhau giữa các ngôn ngữ, hãy đọc this.

+1

Tôi không nên rằng mảng byte chứa 'ÃÃŒ? öà € ABC' được mã hóa dưới dạng ISO-8859-15, có lẽ không phải là Chuỗi mà OP muốn. 'Üü? ÖäABC' được mã hóa là ISO-8859-15 sẽ là mảng' {0x22, (byte) 0xdc, (byte) 0xfc, 0x3f, (byte) 0xf6, (byte) 0xe4, 0x41, 0x42, 0x43, 0x22} ' – McDowell

7

Cấu trúc như new String("Üü?öäABC".getBytes(), "ISO-8859-15");hầu như luôn luôn lỗi.

Những gì bạn đang làm gì ở đây đang thực hiện một đối tượng String, nhận được byte[] tương ứng trong bảng mã mặc định nền tảng và tái diễn giải nó như ISO-8859-15 để chuyển đổi nó trở lại một String.

Nếu mã hóa nền tảng mặc định sẽ xảy ra là tiêu chuẩn ISO-8859-15 (hoặc gần đủ để làm cho có sự khác biệt cho riêng String này, ví dụ ISO-8859-1), sau đó nó là một không-op (tức nó không có tác dụng thực).

Trong mọi trường hợp khác, nó sẽ nhiều khả năng là phá hủy String.

Nếu bạn cố gắng để "sửa chữa" một String, sau đó có lẽ bạn đang quá muộn: nếu bạn phải sử dụng một mã hóa cụ thể để đọc dữ liệu, sau đó bạn nên sử dụng nó tại điểm mà dữ liệu nhị phân được chuyển đổi đến String dữ liệu. Ví dụ: nếu bạn đọc từ số InputStream, bạn cần phải chuyển mã hóa chính xác tới hàm tạo của InputStreamReader.

Đang cố gắng để sửa chữa vấn đề "sau khi thực tế" sẽ

  1. khó thực hiện và
  2. thường thậm chí không thể (vì giải mã một byte[] với mã hóa sai có thể là một hoạt động phá hoại).
1

Các chuỗi Java luôn được lưu trữ nội bộ dưới dạng mảng UTF16 (và dưới dạng UTF8 trong tệp lớp sau khi tuân thủ), vì vậy bạn không thể giải thích một chuỗi giống như chuỗi byte. Nếu bạn muốn tạo mảng byte từ một chuỗi trong một mã hóa nhất định, trước tiên bạn phải chuyển đổi thành mã hóa này:

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

Tôi hy vọng điều này sẽ giải quyết được vấn đề của bạn.

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

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

Và:

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

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

Xin chào Jooce, tôi đã thử như cũ, có vẻ như nó hoạt động tốt, cảm ơn bạn vì điều này – Sundhar

0

tôi muốn cung cấp các thiết lập mở rộng của ký tự để xác nhận chuỗi chuyển đổi từ ISO-8859-1 thành 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

Dưới đây là một cách dễ dàng với String ra (I tạo ra một phương pháp để làm điều này):

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"; 

nó hoạt động !! :)

Các vấn đề liên quan