Статьи

Java: Росіяни букви і не тільки ...

  1. Java: Росіяни букви і не тільки ...
  2. зміст:
  3. Російські літери в исходниках Java-програм.
  4. Російські літери в файлах properties.
  5. Російські літери в Servlet-ах.
  6. GUI (AWT, Swing)
  7. I18n (висновок чисел, дат і т.п.)
  8. Про утиліту native2ascii
  9. Про метод перекодування символів

2000 р

Java: Росіяни букви і не тільки ...

Сергій Астахов ( [email protected] ),
http://www.comita.spb.ru/users/sergeya/java/ruschars.html

Тут я спробував зібрати інформацію з приводу написання російськомовних програм на мові 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-вівцям поки не до таких високих матерій.

До речі, про виведення на консоль. Є два шляхи вирішення вищевказаної проблеми:

  1. Використовувати замість System.out.println свій клас, а вже в ньому робити перетворення. наприклад:
  2. 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 ( "Повідомлення");
  3. Написати свою версію PrintStream, що підтримує потрібне кодування, і підставити його через System.setOut () і System.setErr (). Ось, наприклад, звичайне початок в моїх програмах:
  4. ... 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. Зробити перетворення в потрібне кодування. Якщо ви все зробите коректно, то дані не загубляться, хоча, звичайно, користуватися цим бажано тільки в крайньому випадку. приклад:
  4. // Читання російських букв в кодуванні 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);

    Більш докладно про цей метод, і про можливі проблеми з ним, розписано нижче, в розділі Про метод перекодування символів.

  5. Налаштувати драйвер БД на потрібне кодування. Як саме - це залежить від конкретного драйвера. На жаль, багато драйвера поняття не мають про якісь там кодуваннях. Іноді їх можна пропатчити на цей рахунок, але найчастіше доводиться діяти обхідними шляхами.
  6. Наприклад, один з найбільш часто використовуваних драйверів - міст 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 за замовчуванням - якщо нічого не вказано).

Ім'я файлу, що підлягає формується за допомогою додавання ідентифікатора мови і країни до імені ресурсу. Наприклад, якщо вантажиться ресурс resfile, а поточний Locale - ru_RU, то пошук його буде йти в наступному порядку:

  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 .

Тому користуватися цим методом варто тільки в самому крайньому випадку, коли вже ніщо інше не допомагає, і Ви чітко собі уявляєте, де саме відбувається невірне перетворення символів.

Якщо, при перекодуванні з char в byte не було знайдено відповідного символу, він замінюється на символ?
Куди ж податися бідному російському програмісту?
Так в чому ж особливості?
Де ж дійсно лежать найбільші підводні камені?

Новости