Java Unicode Confusion - PullRequest
       12

Java Unicode Confusion

6 голосов
/ 20 января 2011

Привет всем, я только начал пытаться изучать Java и столкнулся с чем-то, что действительно сбивает с толку!

Я печатал пример из книги, которую я использую. Это продемонстрировать тип данных char.

Код выглядит следующим образом:

public class CharDemo
{
public static void main(String [] args)
{
char a = 'A';
char b = (char) (a + 1);
System.out.println(a + b);
System.out.println("a + b is " + a + b);
int x = 75;
char y = (char) x;
char half = '\u00AB';
System.out.println("y is " + y + " and half is " + half);
}
}

Бит, который меня смущает, это утверждение, char half = '\ u00AB'. В книге говорится, что \ u00AB - это код для символа '1/2'. Как описано, когда я компилирую и запускаю программу из cmd, символ, который создается в этой строке, фактически равен «1/2».

Так что, похоже, все работает как надо. Я решил поиграть с кодом и попробовать разные юникоды. Я погуглил несколько таблиц Юникода и не нашел ни одной из них, согласующихся с приведенным выше результатом.

В каждом найденном мной сообщалось, что код / ​​u00AB был не для «1/2», а фактически для этого:

http://www.fileformat.info/info/unic...r/ab/index.htm Итак, какой набор символов использует Java, я думал, что Unicode должен был быть именно таким, Uni, только один. Я искал часы, и нигде не могу найти набор символов, в котором говорится, что / u00AB равен 1/2, но мой компилятор java интерпретирует его как.

Я, должно быть, здесь упускаю что-то очевидное! Спасибо за любую помощь!

Ответы [ 5 ]

16 голосов
/ 20 января 2011

Это хорошо известная проблема с несоответствием кодировки консоли на платформах Windows.

Java Runtime ожидает, что кодировка, используемая системной консолью, совпадает с кодировкой системы по умолчанию.Однако в Windows используются две отдельные кодировки: кодовая страница ANSI (кодировка системы по умолчанию) и кодовая страница OEM (кодировка консоли) .

Итак, когда вы пытаетесь записать символ Unicode U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK на консоль, среда выполнения Java ожидает, что кодировка консоли является кодировкой ANSI (то есть Windows-1252 в вашем случае), гдеэтот символ Unicode представлен как 0xAB.Однако фактической кодировкой консоли является OEM-кодировка ( CP437 в вашем случае), где 0xAB означает ½.

Поэтому печать данных на консоль Windows с помощью System.out.println() дает неправильные результаты.

Чтобы получить правильные результаты, вы можете использовать System.console().writer().println() вместо.

4 голосов
/ 20 января 2011

Символ \u00ab не является символом 1/2;см. окончательную кодовую страницу с веб-сайта Unicode.org.

То, что вы видите, является (я думаю) следствием использования System.out PrintStreamна платформе, где кодировка символов по умолчанию не UTF-8 или Latin-1.Может быть, это какой-то набор символов Windows, предложенный ответом @ axtavt?(У этого также есть правдоподобное объяснение того, почему \u00ab отображается как 1/2 ... а не как какой-то символ "splat".)

(В Unicode и Latin-1, \00BD является кодовой точкойдля символа 1/2.)

3 голосов
/ 20 января 2011

0xAB - это 1/2 в старом добром кодовая страница 437 , то есть то, что терминалы Windows будут использовать по умолчанию, независимо от того, какую кодовую страницу вы фактически установили .

Таким образом, на самом деле, значение char представляет символ «« »для Java-программы, и если вы отобразите этот символ в GUI или запустите его в нормальной операционной системе, вы получите этот символ. Если вы также хотите видеть правильные результаты в Windows, переключите настройки шрифта в CMD на «Растровые шрифты» (щелкните значок слева вверху, «Свойства», вкладка «Шрифт»). Например, с помощью Lucida Console я могу сделать это:

C:\Users\Documents>java CharDemo
131
a + b is AB
y is K and half is ½    

C:\Users\Documents>chcp 1252
Active code page: 1252

C:\Users\Documents>java CharDemo
131
a + b is AB
y is K and half is «

C:\Users\Documents>chcp 437
Active code page: 437
2 голосов
/ 20 января 2011

Отличительной особенностью Java является то, что она основана на Unicode.Это означает, что вы можете использовать символы из систем записи, которые не являются английскими алфавитами (например, китайские или математические символы), не только в строках данных, но и в именах функций и переменных.

Вот пример кода с использованием символов Юникодав именах классов и именах переменных.

class 方 {
    String 北 = "north";
    double π = 3.14159;
}

class UnicodeTest {
    public static void main(String[] arg) {
        方 x1 = new 方();
        System.out.println( x1.北 );
        System.out.println( x1.π );
    }
}

Java была создана примерно в то время, когда в стандарте Unicode были определены значения для гораздо меньшего набора символов.В то время считалось, что 16-битное число будет более чем достаточно для кодирования всех символов, которые когда-либо понадобятся.Имея это в виду, Java была разработана для использования UTF-16.Фактически тип данных char изначально использовался для представления 16-битной кодовой точки Unicode.

Кодировка UTF-8 определяется RFC 2279;

Кодировки UTF-16 определяются RFC 2781

В кодировках UTF-16 используются шестнадцатиразрядные величины, и поэтому они чувствительны к порядку байтов.В этих кодировках порядок байтов потока может указываться начальной меткой порядка байтов, представленной символом Unicode '\ uFEFF'.Метки порядка байтов обрабатываются следующим образом:

When decoding, the UTF-16BE and UTF-16LE charsets ignore byte-order marks; when encoding, they do not write byte-order marks.

When decoding, the UTF-16 charset interprets a byte-order mark to indicate the byte order of the stream but defaults to big-endian if there is no byte-order mark; when encoding, it uses big-endian byte order and writes a big-endian byte-order mark.

Также смотрите это

0 голосов
/ 20 января 2011

Хорошо, когда я использую этот код, я получаю <<, как я должен, и 1/2 для <code>\u00BD, как и должно быть.

http://www.unicode.org/charts/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...