Java: турецкая кодировка Mac / Windows - PullRequest
2 голосов
/ 15 декабря 2009

У меня проблема с турецкими спецсимволами на разных машинах. Следующий код:

String turkish = "ğüşçĞÜŞÇı";

String test1 = new String(turkish.getBytes());
String test2 = new String(turkish.getBytes("UTF-8"));
String test3 = new String(turkish.getBytes("UTF-8"), "UTF-8");

System.out.println(test1);
System.out.println(test2);
System.out.println(test3);

На Mac три строки совпадают с исходной строкой. На компьютере с Windows три строки (напечатаны с помощью консоли Netbeans 6.7):

?ü?ç?Ü?Ç?
ğüşçĞÜŞÇı
?ü?ç?Ü?Ç?

У меня нет проблем.

Ответы [ 4 ]

11 голосов
/ 15 декабря 2009
String test1 = new String(turkish.getBytes());

Вы берете строку Unicode, включая турецкие символы, и превращаете ее в байты, используя кодировку по умолчанию (использование кодировки по умолчанию обычно является ошибкой). Затем вы берете эти байты и декодируете их обратно в строку, снова используя кодировку по умолчанию. В результате вы ничего не добились (кроме потери любых символов, которые не вписываются в кодировку по умолчанию); если вы поместили строку через цикл кодирования / декодирования, то не повлияет на то, что делает следующий System.out.println(test1), потому что он все еще печатает строку, а не байты.

String test2 = new String(turkish.getBytes("UTF-8"));

Кодирует как UTF-8, а затем декодирует, используя кодировку по умолчанию. На Mac кодировкой по умолчанию является UTF-8, так что это ничего не делает. В Windows кодировкой по умолчанию никогда не является UTF-8, поэтому в результате получаются неправильные символы.

String test3 = new String(turkish.getBytes("UTF-8"), "UTF-8");

Точно ничего не делает.

Чтобы записать строки в стандартный вывод с кодировкой, отличной от кодировки по умолчанию, вы должны создать кодировщик, подобный new OutputStreamWriter(System.out, "cp1252"), и отправить в него содержимое строки.

Однако в этом случае похоже, что консоль использует кодовую страницу Windows 1252 для Западной Европы (+1 ATorres). Здесь вообще нет проблемы несоответствия кодировки, поэтому вы не сможете решить ее путем перекодирования строк!

Кодировка по умолчанию cp1252 соответствует кодировке консоли, просто cp1252 вообще не содержит турецких символов ğşĞŞı. Вы можете видеть, что другие символы, которые равны в cp1252, üçÜÇ, проходят просто отлично. Если вы не можете перенастроить консоль для использования другой кодировки, которая включает все нужные символы, вы не сможете вывести эти символы.

Предположительно, при турецкой установке Windows кодовая страница по умолчанию будет cp1254, и вы получите ожидаемые символы (но другие символы не работают). Вы можете проверить это, изменив настройку «Язык для приложений, не поддерживающих Юникод», в приложении «Язык и региональные стандарты».

К сожалению, ни одна локаль Windows не использует UTF-8 в качестве кодовой страницы по умолчанию. Вывод не-ASCII вывода на консоль с функциями потока stdio вовсе не является чем-то действительно надежным. Существует Win32 API для записи Unicode непосредственно на консоль, но, к сожалению, его мало кто использует.

5 голосов
/ 15 декабря 2009

Не полагайтесь на консоль или кодировку платформы по умолчанию. Всегда указывайте кодировку символов для вызовов, таких как getBytes, и конструктор String, принимающий байтовый массив, и, если вы хотите проверить содержимое строки, выведите значение Unicode для каждого символа.

Я бы также посоветовал либо ограничить ваш исходный код использованием ASCII (и \ uxxxx для кодирования не-ASCII символов) или , явно указав кодировку символов при компиляции. *

Теперь, какую большую проблему вы пытаетесь решить?

2 голосов
/ 15 декабря 2009

Возможно, вы имеете дело с различными настройками кодировки по умолчанию.

java -Dfile.encoding=utf-8

против

java -Dfile.encoding=something else

Или, возможно, вы просто видите, что окно терминала Mac работает в UTF-8, а окно Windows DOS не работает в UTF-8.

Согласно мистеру Скиту, у вас есть третья возможная проблема, которая заключается в том, что вы пытаетесь встроить символы UTF-8 в свой источник. В зависимости от параметров компилятора, вы можете или не можете получить то, что вы намеревались там. Поместите эти данные в файл свойств или используйте \ u escape.

Наконец, также, по словам мистера Скита, никогда не вызывайте getBytes () с нулевым аргументом.

0 голосов
/ 15 декабря 2009

Если вы используете компилятор AspectJ, не забудьте также установить для него кодировку UTF-8. Я пытался найти это часами.

...