Почему java не выводит русский текст
Перейти к содержимому

Почему java не выводит русский текст

  • автор:

Почему на JSP странице русские символы отображаются кракозябрами?

У меня случилось так, что при интернационализации моего веб-проекта, русские символы отображаются кракозябрами.
Что я делал:
1. Я использую properties-файлы, в которых на нужном языке пишу текст. Нужно проверить, чтобы текст в данных файлах был установлен как UTF-8.

Это не помогло. Идём дальше.

2. Через Filter задать кодировку UTF-8.

Создаем фильтр, в котором будем устанавливать кодировку UTF-8 для request и response:

@WebFilter(filterName = "EncodingFilter", urlPatterns = ) public class EncodingFilter implements Filter < private static final Logger LOGGER = LogManager.getLogger(); private final static String ENCODING_UTF_8 = "UTF-8"; @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException < LOGGER.info("Current encoding for request: <>, for response: <>.", servletRequest.getCharacterEncoding(), servletResponse.getCharacterEncoding()); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; request.setCharacterEncoding(ENCODING_UTF_8); response.setCharacterEncoding(ENCODING_UTF_8); LOGGER.info("Set encoding for request: <>, for response: <>.", request.getCharacterEncoding(), response.getCharacterEncoding()); filterChain.doFilter(request, response); > >

Но и это не помогло. Идём дальше.

3. Для каждой jsp-страницы нужно также задать кодировку UTF-8.

Сделать это можно двумя способами:

1. Прописав в web.xml файле настройки:

   *.jsp UTF-8  

2. Прописать на каждой jsp-странице:

Но и это не помогло. Идём дальше.

4. Потом я, согласно [документации](tomcat.apache.org/tomcat-7.0-doc/config/http.html), настроил `Tomcat` следующим образом.

Открываем файл C:\Program Files\Apache Software Foundation\Tomcat 10.0\conf\server.xml и добавляем в секцию атрибут URIEncoding=»UTF-8″. В конечном итоге секция будет выглядеть следующим образом:

Но и это не помогло. Перезагрузил ноутбук, думал поможет, но не заработало. Опять идём дальше.

5. Добавляем на jsp-страницу вот это:

На выходе получаю:

ÐÐ»Ð°Ð²Ð½Ð°Ñ Ð Ð½Ð°Ñ ÐонÑакÑÑ

И это тоже не работает. В чем проблема?

  • Вопрос задан более двух лет назад
  • 1828 просмотров

Как вывести русский(кириллица) текст на экран?

Author24 — интернет-сервис помощи студентам

Здравствуйте, я ввел данные у файл, и вот оно выводит такую. подскажите что нужно подключить или изменить?

94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Xcode , С++ и русский язык: как вывести в файл русский текст без сбитой кодировки?
Как сделать так, чтобы после некоторых манипуляций в файл выводился русский текст без сбитой.

Как вывести русский текст из файла
Подскажите пожалуйста, как сделать, чтобы русский текст не вопросами появлялся. Английский текст и.

Как вывести русский текст в ассемблере?
org 100h begin: mov cl, Label1: mov ah,9 mov dx,offset String int 21h .

Как в файл вывести русский текст?
Когда русский текст вывожу в файл выводит какую то какафонию как это исправить

Am I evil? Yes, I am!

Эксперт PythonЭксперт Java

17221 / 10148 / 2790
Регистрация: 21.10.2017
Сообщений: 22,152

Ты уж определись.
)))
Am I evil? Yes, I am!

Эксперт PythonЭксперт Java

17221 / 10148 / 2790
Регистрация: 21.10.2017
Сообщений: 22,152

ЦитатаСообщение от Oleksandr1103 Посмотреть сообщение

ввел данные у файл
Файл-то в какой кодировке?
Регистрация: 05.03.2022
Сообщений: 132

ЦитатаСообщение от iSmokeJC Посмотреть сообщение

Ты уж определись.

я пробывал ставить windows-1251, но только хуже стало, оно и латинь перестало выводить. кодировка файла windows-1251

Am I evil? Yes, I am!

Эксперт PythonЭксперт Java

17221 / 10148 / 2790
Регистрация: 21.10.2017
Сообщений: 22,152
Oleksandr1103, ну так сконвертируй в utf-8
Регистрация: 05.03.2022
Сообщений: 132

ЦитатаСообщение от iSmokeJC Посмотреть сообщение

сделал, ничего не изменилось
Am I evil? Yes, I am!

Эксперт PythonЭксперт Java

17221 / 10148 / 2790
Регистрация: 21.10.2017
Сообщений: 22,152
Когда файл открываешь, указывай кодировку
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Как вывести русский текст в консоль?
Что-то я совсем запутался с кодировкой в python, версия стоит 2.7.4 пытаюсь выводить в консоль.

Русская кодировка в БД, как вывести на страницу русский текст?
Привет всем, у меня сложилась такая проблема, есть база данных, есть таблица с названиями городов.

В файле содержится текст. Вывести в отдельный текстовый файл первые буквы всех слов (русский текст)
Можно пожалуйста код с нуля

Как в массиве заменить определенный текст на другой и вывести новый полученный текст на экран?
Как в массиве заменить определенный текст на другой и вывести новый полученный текст на экран ? .

пдскажите функцию которая выводит русский текст на экран и его заголовочный файл с++ но не system ( » echo текст » );
пдскажите функцию которая выводит русский текст на экран и его заголовочный файл с++ но не system (.

Вывести русский текст
Помогите пожалуйста, как вывести в консоль не просто русский текст, а именно вывести текст из.

Или воспользуйтесь поиском по форуму:

Почему java не выводит русский текст

Может такой вопрос и вставал, но я не нашЁл

WinNT,Win2k,WinXP — и русские и аглицкие

public class Test < public static void main(String[] args) < System.out.println("Тестовый текст на русском языке"); > >

компилю
запускаю консоль cmd.exe
выполняю java Test
Вместо русского текста получаю кракозяблы. Т.е. текст выводится в кодировке 1251, а консоль показывает 866

Как решить проблему?

Что ни делается, всЁ к лучшему
Re: Русский текст в консоли

От: Blazkowicz
Дата: 16.09.03 07:11
Оценка:

Здравствуйте, SmaLL75, Вы писали:

SLL>запускаю консоль cmd.exe
SLL>выполняю java Test
SLL>Вместо русского текста получаю кракозяблы. Т.е. текст выводится в кодировке 1251, а консоль показывает 866

Честно говоря, странно. У меня W2K и всё чудесно выводиться в консоль по русски. Может у тебя .java файл не в той кодировке сохранён.

Re: Русский текст в консоли

От: Korikoff Pavel http://www.intrice.com/
Дата: 16.09.03 07:20
Оценка:

Добавьте следующий параметр к javac:

-encoding

с указанием соответствующей кодировки.
Re[2]: Русский текст в консоли

От: SmaLL75 http://smallweb.narod.ru
Дата: 16.09.03 07:26
Оценка:

Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, SmaLL75, Вы писали:

SLL>>запускаю консоль cmd.exe
SLL>>выполняю java Test
SLL>>Вместо русского текста получаю кракозяблы. Т.е. текст выводится в кодировке 1251, а консоль показывает 866

B>Честно говоря, странно. У меня W2K и всё чудесно выводиться в консоль по русски. Может у тебя .java файл не в той кодировке сохранён.

Файл в виндовой кодировке (как проверка — блокнот отображает нормально)

У меня такая же проблема с Ораклом, он же тоже яву использует, как только ставлю русскую локаль, так пишет кракозяблы

Что ни делается, всЁ к лучшему
Re[2]: Русский текст в консоли

От: SmaLL75 http://smallweb.narod.ru
Дата: 16.09.03 07:53
Оценка:

Здравствуйте, Korikoff Pavel, Вы писали:

KP>Добавьте следующий параметр к javac:
KP>

KP>-encoding KP>

KP>с указанием соответствующей кодировки.

Не помогает
А вообще я использую Идею, а там с этим делом — порядок

Что ни делается, всЁ к лучшему
Re: Русский текст в консоли

От: Cider
Дата: 16.09.03 08:03
Оценка: 1 (1)

Здравствуйте, SmaLL75, Вы писали:

SLL>Как решить проблему?

По-моему, никак
Консоль работает в какой-то своей кодировке, прога — в своей. Чтобы решить эту проблему, надо привести в соответствие кодировки программы и консоли. Можно самому написать консоль Или если известна кодировка консоли можно задать эту кодировку при компиляции и выводе текста.

 String text = "Русский текст"; try < System.out.write(text.getBytes("")); > catch (IOException e)

И в любом случае, если удастся сделать это на одной машине, на остальных все равно будут ероглифы.
Пишите по-аглицки

Почему java не выводит русский текст

Здесь я попытался собрать информацию по поводу написания русскоязычных программ на языке Java. Если Вам известно что-либо помимо того, что я тут понаписал, напишите мне, ваши добавления будут кстати.

Файлы данных, потоки, БД.

Итак, как все, надеюсь, знают, в языке Java для представления символов используется Unicode, т.е. по два байта на один символ (тип char размером в 16 бит). В набор символов входят всевозможные буквы со всякими чёрточками и припендюльками, греческие, математические и символы псевдографики. В том числе и так любимые нами символы кириллицы (диапазон значений 0x0400-0x04ff). Так что с этой стороны никакой дискриминации нет.

Если Вам интересны конкретные кода символов, для их просмотра удобно использовать программу «Таблица символов» из WinNT. Вот, например, диапазон кириллицы:

С другой стороны большинство файлов данных основано на 8-битовом представлении символов. Сюда входят также текстовые файлы и большинство баз данных (окромя наиболее продвинутых). Кроме того, что самое паршивое, одни и те же байты могут представлять разные символы (в зависимости от кодовой страницы). Налицо конфликт — как преобразовать одно в другое и наоборот, причём с наименьшими потерями для данных. Для этого был придуман довольно удобный механизм использования кодовых страниц. Для каждой кодовой страницы было создано по 2 класса перекодировки (ByteToChar и CharToByte). Классы эти лежат в пакете sun.io. Если, при перекодировке из char в byte не было найдено соответствующего символа, он заменяется на символ ?.

Кстати, эти файлы кодовых страниц в некоторых ранних версиях JDK 1.1 содержат ошибки, вызывающие ошибки перекодировок, а то и вообще исключения при выполнении. Например, это касается кодировки KOI8_R. Лучшее, что можно при этом сделать — сменить версию на более позднюю. Судя по Sun-овскому описанию, большинство этих проблем было решено в версии JDK 1.1.6.

Когда и как надлежит пользоваться этой перекодировкой? Когда пользоваться, в принципе, понятно — при любом преобразовании из byte в char и наоборот. В классе String в тех местах, где есть преобразование можно указать дополнительный параметр (String enc), задающий имя кодовой страницы. Это конструктор по массиву байтов и метод getBytes(). Однако, в реальной программе, явно указывать кодовую страницу не всегда удобно. Для этого была введена кодировка по умолчанию. По умолчанию она зависит от системы (для русских виндов принята кодировка Cp1251), и в старых JDK её можно изменить установкой системного свойства file.encoding. Вообще-то, как утверждают в Sun, это свойство отражает системную кодировку, и она не должна изменяться в командной строке (см., например, комментарии к BugID 4256423) Эта кодировка используется тогда, когда явно не указанно название страницы. Т.к. эта настройка одна на все преобразования, иногда можно наткнуться на неприятности. Например, эта же настройка используется для вывода на консольный экран, что, в случае виндов, как правило, неприемлемо — там нужно использовать страницу Cp866. Было бы здорово, если бы эти кодировки указывались независимо — например, console.encoding и т.п., но, думаю, Sun-овцам пока не до таких высоких материй.

    Использовать вместо System.out.println свой класс, а уже в нём делать преобразование. Например:

public class Msg < static String cp = System.getProperty("console.encoding","Cp866"); public static void message(String msg) < msg += "\n"; byte[] b; try < b = msg.getBytes(cp); >catch( UnsupportedEncodingException e ) < b = msg.getBytes(); // В случае отсутствия нужной кодировки, // делаем преобразование по умолчанию >System.out.write(b); > > . Msg.message("Сообщение");
. public static void main(String[] args) < // Установка вывода консольных сообщений в нужной кодировке try < System.setOut(new CodepagePrintStream(System.out,System.getProperty("console.encoding","Cp866")) ); >catch(UnsupportedEncodingException e) < System.out.println("Unable to setup console codepage: " + e); >.
  1. Читать и записывать массивы байтов (byte[]), а для перекодировки использовать упомянутые методы класса String. Этот способ особенно удобен, когда в потоке могут присутствовать данные в разных кодировках.
  2. Использовать классы InputStreamReader и OutputStreamWriter из пакета java.io, специально предназначенные для этих целей.
  3. Сделать преобразование в нужную кодировку. Если вы всё сделаете корректно, то данные не потеряются, хотя, конечно, пользоваться этим желательно только в крайнем случае. Пример:

// Чтение русских букв в кодировке Cp866 через объект, // поддерживающий только Cp437 String str = o.readString(); str = new String(str.getBytes("Cp437"),"Cp866"); // Сохранение русских букв в кодировке Cp866 через объект, // поддерживающий только Cp437 str = new String(str.getBytes("Cp866"),"Cp437"); o.writeString(str);

Например, один из самых часто используемых драйверов — мост JDBC-ODBC. В версиях JDK 1.1, этот мост просто игнорировал кодировки символов, из-за чего нужно было предпринять дополнительные ухищрения, типа описанных в предыдущем пункте (это также касается и последней ихней версии, 1.1.8).

Мост из комплекта Sun Java 2 теперь можно настроить на нужную кодировку. Это делается добавлением дополнительного свойства charSet в набор параметров, передаваемых для открытия соединения с базой. По умолчанию используется file.encoding. Делается это примерно так:

// Параметры соединения с базой Properties connInfo = new Properties(); connInfo.put("user", username); connInfo.put("password", password); connInfo.put("charSet", "Cp1251"); // Устанавливаем соединение Connection db = DriverManager.getConnection(dataurl, connInfo);

Другой пример — драйвер JDBC-OCI (не pure Java — тот называется thin) от Oracle 8.0.5 под Linux. При получении данных из БД, драйвер определяет «свою» кодировку при помощи переменной окружения NLS_LANG. Если эта переменная не найдена, то он считает что кодировка — ISO88591. Весь фокус в том, что NLS_LANG должна быть именно переменной окружения, а properties (типа file.encoding) здесь «не катят». В случае использования драйвера внутри servlet engine Apache+Jserv, переменную окружения можно задать в файле jserv.properties:

wrapper.env=NLS_LANG=American_America.CL8KOI8R

Если же Вы свободны в формировании формата — тогда всё проще. Используйте формат Unicode или UTF8 — и проблем не будет.

В случае с БД, можно, конечно, использовать и какой-нибудь 16-ричный формат, но это не всегда приемлемо, т.к. Вы получите 2-х — 4-х кратный рост места на диске и потеряете возможность использовать стандартные программы работы с БД, например генераторы отчётов.

Русские буквы в исходниках Java-программ.

Как уже упоминалось, при выполнении программы используется Unicode. Исходные же файлы пишутся в обычных редакторах. Я пользуюсь Far-ом, у Вас, наверняка есть свой любимый редактор. Эти редакторы сохраняют файлы в 8-битовом формате, а значит, что к этим файлам также применимы рассуждения, аналогичные приведённым выше. Разные версии компиляторов немного по разному выполняют преобразование символов. В ранних версиях JDK 1.1.x используется настройка file.encoding, которую можно поменять при помощи нестандартной опции -J. В более новых (как сообщил Денис Кокарев — начиная с 1.1.4) был введён дополнительный параметр -encoding, при помощи которого можно указать используемую кодировку. В скомпилированных классах строки представлены в виде Unicode (точнее в модифицированном варианте формата UTF8), так что самое интересное происходит при компиляции. Поэтому, самое главное — выяснить, в какой кодировке у Вас исходники и указать правильное значение при компиляции. По умолчанию будет использован всё тот же пресловутый file.encoding. Пример вызова компилятора:

javac -encoding=KOI8_R .

Кроме использования этой настройки есть ещё один метод — указывать буквы в формате «\uxxxx», где указывается код символа. Этот метод работает со всеми версиями, а для получения этих кодов можно использовать стандартную утилиту native2ascii.

Русские буквы в файлах properties.

Для чтения файлов properties используются методы загрузки ресурсов, которые работают специфичным образом. Собственно для чтения используется метод Properties.load, который не использует file.encoding (там кодировка жёстко указана), поэтому единственный способ указать русские буквы — использовать формат «\uxxxx» и утилиту native2ascii.

Метод Properties.save работает по разному в версиях JDK 1.1 и 1.2. В версиях 1.1 он просто отбрасывал старший байт, поэтому правильно работал только с англицкими буквами. В 1.2 делается обратное преобразование в «\uxxxx», так что он работает зеркально к методу load.

Русские буквы в Servlet-ах.

Ну, для чего эти самые Servlet-ы нужны, я думаю, Вы в курсе. Если нет — то лучше сначала прочитать документацию. Здесь же рассказывается только об особенностях работы с русскими буквами.

Так в чём же особенности? Когда Servlet посылает ответ клиенту, есть два способа послать этот ответ — через OutputStream (getOutputStream()) или через PrintWriter (getWriter()). В первом случае Вы записываете массивы байтов, поэтому применимы вышеописанные методы записи в файл. В случае же PrintWriter, он использует установленную кодировку. В любом случае необходимо правильно указать используемую кодировку при вызове метода setContentType(), для того, чтобы было правильное преобразование символов на стороне сервера. Это указание должно быть сделано перед вызовом getWriter() или перед первой записью в OutputStream. Пример:

public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException < response.setContentType("text/html; charset=windows-1251")); PrintWriter out = response.getWriter(); // Отладочный вывод названия кодировки для проверки out.println( "Encoding: " + response.getCharacterEncoding() ); . out.close();

Это по поводу отдачи ответов клиенту. Со входными параметрами, к сожалению не так просто. Входные параметры кодируются броузером побайтно в соответствии с MIME-типом "application/x-www-form-urlencoded". Как рассказал Алексей Менделев русские буквы броузеры кодируют, используя текущую установленную кодировку. Ну и, разумеется, ничего о ней не сообщают. Соотвественно, например, в JSDK 2.0 и 2.1 это никак не проверяется. Собственно для раскодирования используются методы HttpUtils.parsePostData() и HttpUtils.parseQueryString(), которые просто обнуляют старший байт. Это зарегистрированная ошибка в JSDK (4154966). К сожалению, эту ошибку закрыли как "Will not be fixed", с тем оправданием, что, дескать, раз в RFC на эту тему ничего не сказанно, то и делать мы ничего не будем. Однако, после переписки наших разработчиков в майл-листе SERVLET-INTEREST дело, похоже, сдвинулось с мёртвой точки. По крайней мере на словах было обещано включить метод установки кодировки в спецификацию JSDK 2.3.

Пока же приходится обходиться своими средствами. Оригинальный способ работы с кодировками предлагает Russian Apache - здесь расписано, как именно. Судя по отзывам, не имеет проблем с русскими и система Resin.

Своё решение проблемы так же предложил Вячеслав Педак.

Ну а самый простейший вариант извлечь таки символы - передавать в комплекте параметров имя кодировки (или, если вы уверены в текущей кодировке броузера, использовать предопределённую кодировку) и использовать метод перекодировки символов:

public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException < // Кодировка сообщений // В связке MSIE 4.01 SP1 ->JSDK 2.0 servletrunner.exe всегда выдаёт "ISO-8859-1" String requestEnc = request.getCharacterEncoding(); // Некоторые servlet engine, не мудрствуя лукаво, возвращают null if( requestEnc==null ) requestEnc="ISO-8859-1"; String clientEnc = request.getParameter("charset"); if( clientEnc==null ) clientEnc="Cp1251"; String value = new String(request.getParameter("value").getBytes(requestEnc),clientEnc);

В общем, опыт в написании Servlet-ов у меня небольшой, так что Ваши замечания будут приветствоваться.

GUI (AWT, Swing)

Многие связывают неправильный вывод русских букв с неправильной установкой шрифта. Мне кажется, это связанно с тяжким опытом программирования на Windows 3.x, где основная причина действительно была в этом. В Java всё сложнее и редко действительно связанно со шрифтами. Я не разбирался со специфическими настройками броузеров, т.к. ещё не писал апплетов, только приложения, но думаю в последних версиях в этом плане всё нормально.

Где же действительно лежат наибольшие подводные камни? В основном это связанно с неправильной перекодировкой символов. Часть этих проблем и методы их решения описаны выше. Если у Вас все преобразования выполняются корректно, и для вывода используется шрифт Unicode, то есть очень большой шанс, что Ваша программа будет работать правильно.

Если проблемы всё же остались, тут нужно выяснить, где они возникают. Попробуйте запустить приложение под разными JVM, под разными платформами, на разных броузерах.

Если программа не работает нигде - значит проблема только в ней и в ваших руках. Внимательно перечитайте всё, что было написано выше, и ищите. Если же проблема проявляется только в конкретном окружении - значит дело, скорей всего в настройках. Где именно - зависит от того, какой графической библиотекой Вы пользуетесь. Если AWT - помочь может правильная настройка файла font.properties.ru. Пример корректного файла можно взять из Java 2. Если у Вас нет этой версии, можете скачать его с данного сайта: версия для Windows, версия для Linux. Если у Вас установлена русская версия OS - просто добавьте этот файл туда, где лежит файл font.properties. Если же это англицкая версия, то нужно, или дополнительно сменить текущий язык при помощи задания настройки -Duser.language=ru или переписать этот файл вместо font.properties. Этот файл задаёт используемые шрифты и кодовые страницы.

С библиотекой Swing всё проще - в ней всё рисуется через подсистему Java2D. Надписи в стандартных диалогах (JOptionPane, JFileChooser, JColorChooser) переделать на русский очень просто - достаточно лишь создать несколько файлов ресурсов. Я это уже проделал, так что можете просто взять готовый файл и добавить его в свой CLASSPATH. Единственная проблема, с которой я столкнулся - в версиях JDK начиная с 1.2 rc1 и по 1.3 beta, русские буквы не выводятся под Win9x при использовании стандартных шрифтов (Arial, Courier New, Times New Roman, etc.) из-за ошибки в Java2D. Ошибка весьма своеобразна - со стандартными шрифтами изображения букв отображаются не в соответствии с кодами Unicode, а по таблице Cp1251 (кодировка Ansi). Эта ошибка зарегистрирована в BugParade под номером 4192443. По умолчанию в Swing используются шрифты, задаваемые в файле font.properties.ru, так что достаточно заменить их другими - и русские буквы появляются. К сожалению, набор рабочих шрифтов небольшой - это шрифты Tahoma, Tahoma Bold и два набора шрифтов из дистрибутива JDK - Lucida Sans * и Lucida Typewriter * (пример файла font.properties.ru). Чем эти шрифты отличаются от стандартных - мне непонятно.

Начиная с версии 1.3rc1 эта проблема уже исправлена, так что можно просто обновить JDK. Так же надо учесть, что с оригинальной версией Win95 поставляются шрифты, не поддерживающие Unicode - в этой ситуации можно просто скопировать шрифты из Win98 или WinNT.

Если же вам, кровь из носу, нужно использовать стандартные шрифты, работая в JDK 1.2, то можно компенсировать этот глюк, перекодировав строки текста непосредственно перед выводом. Сделать это можно, например, так:

public static String convertToWin9x(String s) < byte[] bb; try < bb = s.getBytes("Cp1251"); >catch( java.io.UnsupportedEncodingException e ) < return s; >char[] cb = new char[bb.length]; for(int i=0; i < bb.length; i++) < cb[i] = (char)( bb[i] & 0x00FF ); >return new String(cb); >

Но только не забудьте - этот код будет работать только под Win9x и Sun JDK/JRE 1.2.

По поводу компилятора jikes. Как мне рассказали в конференции по Java (fido7.ru.java) при использовании этого компилятора русские буквы тоже появляются. Это на самом деле классический пример того, как один глюк компенсирует другой - jikes просто не учитывает кодировку исходников. Того же эффекта можно добиться, если указать javac кодировку ISO-8859-1 (Latin1) в ключике -encoding. Если при этом в исходниках русские символы записаны в кодировке Cp1251, то тем самым они вместо диапазона 0x400-0x4ff (стандартный диапазон Unicode для кириллицы) попадают в диапазон 0x80-0xff. Из-за вышеупомянутого глюка в среде Win9x кириллица в стандартных шрифтах отображается как раз в этом диапазоне и русские буквы появляются. Если же попробовать запустить программу в другой среде (например, в WinNT) - русских букв не будет, так как там этот глюк отсутствует.

Аналогично на подобную компенсацию можно нарваться, если поменять региональные настройки с русских на буржуйские. При этом, кроме всего прочего, меняется и кодировка по умолчанию (file.encoding) - вместо 1251 становится 1252. Это приводит к тому, что, если при чтении файлов кодировка не была явно указана (и при компиляции не задавался ключик -encoding), то русские буквы переезжают в диапазон 0x80-0xff и создаётся впечатление нормальной работы. Разницу можно заметить на преобразованиях регистра и сортировках через java.text.Collator - они будут выполняться неверно. А если были использованы строковые константы - то на других платформах вы увидите только кракозяблы.

Ещё один способ - скачать версию Swing для JDK 1.1 и запускать приложение из под Microsoft JVM - там всё выводится корректно. Только не забудьте обновить MS JVM - те версии, что идут в комплекте с IE 4.x не совсем корректно работают. С сервера Microsoft можно скачать свежую версию, например 5.00.3240 - с ней всё ОК.

Кстати, по поводу MS JVM. Непонятно по каким соображениям, но в ней отсутствуют все файлы кодировок русских букв, акромя Cp1251 (наверное, они таким образом пытались уменьшить размер дистрибутива). Если Вам нужны другие кодировки, например, Cp866, то нужно добавить соответствующие классы в CLASSPATH. Причём классы от последних версий Sun JDK не подходят - у Sun-а уже давно изменилась их структура, поэтому последние версии классов с Microsoft-ом не стыкуются (у MS осталась структура от JDK 1.1.4). На сервере Microsoft, в принципе, лежит полный комплект дополнительных кодировок (страница "Miscellaneous Resources", ссылка "Additional I/O libraries"), но там файл размером около 3 метров, а их сервер докачку не поддерживает :-). Мне удалось таки выкачать этот файл, я его перепаковал jar-ом, можете взять его отсюда.

I18n (вывод чисел, дат и т.п.)

Загадочная комбинация i18n расшифровывается просто - это сокращение от могучего слова Internationalization. 18 - это кол-во букв между i и n. Означает оно, в контексте Java, возможность автоматической подстройки программы под текущий язык и специфику страны. Делается это через использование класса Locale, представляющего язык и конкретную страну, и классов, которые знают, что с этим Locale делать. Большинство этих классов находятся в пакете java.text.

Основной класс, которым пользуются все остальные, - это java.util.ResourceBundle, который позволяет загружать различные виды ресурсов. Причём имя загружаемого класса или файла properties зависит от указанного Locale (или Locale по умолчанию - если ничего не указанно).

  1. resfile_ru_RU.class
  2. resfile_ru_RU.properties
  3. resfile_ru.class
  4. resfile_ru.properties
  5. resfile.class
  6. resfile.properties

Это позволяет легко добавлять описания для новых языков и стран. Большинство классов сами заботятся обо всей этой внутренней кухне, так что Вам об этом знать часто и не нужно.

Что касается дат, то само форматирование выполняется классом DateFormat. Получить формат, уже настроенный на язык и страну можно при помощи методов getDateInstance(), getTimeInstance() и getDateTimeInstance(). В качестве аргумента можно указать одну из констант для задания необходимого стиля формата. По умолчанию будет использован предпочтительный стиль для данного Locale. Допустимые константы:

Константа Описание Пример
SHORT Полностью цифровой, короткий вывод 25.01.99 или 17:40
MEDIUM Вывод средней длины 25.01.1999
LONG Длинный вывод 25 Январь 1999 г. или 17:23:32
FULL Вся информация Понедельник, 25 января 1999 г. или 17:23:32 GMT+03:00
// Вывод пользователю текущей даты DateFormat df = DateFormat.getDateInstance(); String s = df.format(new Date()); . // Вывод текущего времени без секунд DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT); String s = df.format(new Date());

Если же вы хотите сами контролировать набор выводимых полей и их разделители, то для этого можно использовать класс SimpleDateFormat.

Аналогичным образом делается и форматирование чисел. За это отвечает класс NumberFormat. Получить форматы можно при помощи методов getInstance(), getNumberInstance(), getCurrencyInstance() и getPercentInstance(). Свой формат можно сконструировать при помощи класса DecimalFormat.

Об утилите native2ascii

Эта утилита входит в состав Sun JDK и предназначена для преобразования исходных текстов к ASCII-виду. Эта утилита, при запуске без параметров, работает со стандартным входом (stdin) а не выводит подсказку по ключам, как остальные утилиты. Это приводит к тому, что многие и не догадываются о необходимости указания параметров (кроме, может быть, тех, кто нашёл в себе силы и мужество заглянуть таки в документацию :-). Между тем этой утилите для правильной работы необходимо, как минимум, указать используемую кодировку (ключик -encoding). Если этого не сделать, то будет использована кодировка по умолчанию (file.encoding), что может несколько расходится с ожидаемой. В результате, получив неверные кода букв (из-за неверной кодировки) можно потратить весьма много времени на поиск ошибок в абсолютно верном коде.

О методе перекодировки символов

Этот метод многие используют неправильно, наверное, не совсем понимая его суть и ограничения. Он предназначен для восстановления верных кодов букв, если они были неверно проинтерпретированны. Суть метода проста: из полученных неверных символов, используя соответствующую кодовую страницу, восстанавливается исходный массив байтов. Затем из этого массива байтов, используя уже корректную страницу, получаются нормальные кода символов. Пример:

String res = new String( src.getBytes("ISO-8859-1"),"Cp1251");

Проблем в использовании этого приёма может быть несколько. Например, для восстановления используется неверная страница, или же она может измениться в некоторых ситуациях. Другая проблема может быть в том, что некоторые страницы выполняют неоднозначное преобразование byte char. Смотрите, например, описание ошибки за номером 4296969.

Поэтому пользоваться этим методом стоит только в самом крайнем случае, когда уже ничто другое не помогает, и Вы чётко себе представляете, где именно происходит неверное преобразование символов.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *