Итак, несколько вещей.
Прежде всего странице вы связаны говорит, что это о диапазоне точки кода в вопросе:
выдвинутом Коды ASCII (код символа 128-255)
Есть несколько различных вариантов 8-разрядной таблицы ASCII. Нижеследующая таблица соответствует ISO 8859-1, также называемому ISO Latin-1. Коды 128-159 содержат расширенные символы Microsoft® Windows Latin-1.
Это неверно, или, по крайней мере, для меня, вводящим в заблуждение. ISO 8859-1/Latin-1 does not define code point 146 (и another reference just because). Так что это уже просит неприятностей. Вы можете увидеть это также, если вы делаете преобразование через String
:
String s = new String(new byte[] {(byte)146}, "iso-8859-1");
System.out.println(s);
Выходы же «неожиданный» результат. Это появляется, что они на самом деле ссылаются на набор Windows-1252 (он же «Windows Latin-1», но это имя почти полностью устарело в эти дни), который определяет эту кодовую точку как правую одиночную кавычку (для других кодировок которые обеспечивают этот символ на 146 см this list и искать кодировки, которые обеспечивают его на 0x92), и мы можем убедиться в этом, как, например:
String s = new String(new byte[] {(byte)146}, "windows-1252");
System.out.println(s);
так первая ошибка состоит в том, что страница запутанная.
Но большая ошибка заключается в том, что вы не можете делать то, что вы пытаетесь сделать так, как вы это делаете. A char
в Java - это кодовая точка UTF-16 (или половина из них, если вы представляете дополнительные символы> 0xFFFF, один char
соответствует точке BMP, пара из них или int
соответствует всему диапазону, включая дополнительные).
К сожалению, Java действительно не предоставляет много API для односимвольных преобразований. Даже Character
не имеет доступных способов конвертировать из кодировки по вашему выбору в UTF-16.
Таким образом, один из вариантов заключается в том, чтобы сделать это через String
, как указано в приведенных выше примерах, например.выражать свои кодовые точки в качестве исходного массива byte[]
и конвертировать оттуда:
String s = new String(new byte[] {(byte)146}, "windows-1252");
System.out.println(s);
char c = s.charAt(0);
System.out.println(c);
Вы могли захватить char
снова через s.charAt(0)
. Обратите внимание, что при этом вы должны помнить о своем наборе символов. Здесь мы знаем, что наша байтовая последовательность действительна для указанной кодировки, и мы знаем, что результат остается только одним , поэтому мы можем это сделать.
Однако вы должны следить за вещами в общем случае. Например, возможно, ваша последовательность байтов и набор символов дают результат, который находится в дополнительном диапазоне символов UTF-16. В этом случае s.charAt(0)
будет недостаточным, и вместо этого потребуется s.codePointAt(0)
, сохраненный в int
.
В качестве альтернативы, с теми же оговорками, можно использовать Charset
для декодирования, хотя это так же, как неуклюжий, например:
Charset cs = Charset.forName("windows-1252");
CharBuffer cb = cs.decode(ByteBuffer.wrap(new byte[] {(byte)146}));
char c = cb.get(0);
System.out.println(c);
Обратите внимание, что я не совсем уверен, как Charset#decode
обрабатывает дополнительные символы и может» t действительно тестируйте прямо сейчас (но кто-нибудь, не стесняйтесь звонить).
Как и в сторону: В вашем случае, 146 (0x92) отливать непосредственно char
соответствует UTF-16 символ «PRIVATE USE ДВА» (see also), и все ставки выключены для того, что вы будете в конечном показывая там. Этот символ равен classified by Unicode as a control character и, кажется, попадает в диапазон символов, зарезервированных для управления терминалом ANSI (хотя AFAIK фактически не используется, но он находится в этом диапазоне независимо). Я бы не удивился, если бы браузеры в некоторых локалях отображали его как правую одиночную кавычку для совместимости, но терминалы сделали с ней что-то странное.
Кроме того, fyi, официальный код UTF-16 для right single quote is 0x2019. Вы можете надежно хранить, что в char
, используя это значение, например:
System.out.println((char)0x2019);
Вы также можете увидеть это для себя, глядя на значение после преобразования из окон-1252:
String s = new String(new byte[] {(byte)146}, "windows-1252");
char c = s.charAt(0);
System.out.printf("0x%x\n", (int)c); // outputs 0x2019
Или , для полноты:
String s = new String(new byte[] {(byte)146}, "windows-1252");
int cp = s.codePointAt(0);
System.out.printf("0x%x\n", cp); // outputs 0x2019
"Extended ASCII" является неправильным произведением. ASCII по определению имеет значение до 127. Есть наборы символов, которые расширяют этот диапазон, но как они это делают, это дико меняется. Поэтому вам действительно нужно знать, о чем вы говорите. Что вы делаете в своем коде, печатает кодовый номер Unicode 146, который совпадает с одной верхней цитатой, к счастью: http://www.fileformat.info/info/unicode/char/92/index.htm –
Возможно, ваш ответ здесь : http://stackoverflow.com/questions/13012871/converting-ascii-code-to-char-in-java –
на моем входе У меня есть десятичные числа, превышающие 127. Некоторые из них преобразуются правильно, но некоторые вроде 146 приносят неприятности. – Paresh