загрузка...

трусы женские
загрузка...
Реферати » Реферати з інформатики та програмування » Java: Росіяни букви і не тільки ...

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

Введення

Деякі проблеми настільки складні, що потрібно бути дуже розумним і дуже добре поінформованим, щоб не бути впевненим у їх вирішенні.

Лоренс Дж. Пітер

Peter's Almanac

Кодування

Коли я тільки починав програмувати мовою C, першою моєю програмою (не рахуючи HelloWorld) була програма перекодування текстових файлів з основної кодування ГОСТ-а (пам'ятаєте таку? :-) в альтернативну. Було це в далекому 1991-му році. З тих пір багато чого змінилося, але за минулі 10 років подібні програмки свою актуальність, на жаль, не втратили. Занадто багато вже накопичено даних у різноманітних кодуваннях і занадто багато використовується програм, які вміють працювати тільки з однією. Для російської мови існує не менше десятка різних кодувань, що робить проблему ще більш заплутаною.

Звідки ж узялися всі ці кодування і для чого вони потрібні? Комп'ютери за своєю природою можуть працювати тільки з числами. Для того щоб зберігати букви в пам'яті комп'ютера треба поставити у відповідність кожній букві якесь число (приблизно такий же принцип використовувався і до появи комп'ютерів - згадайте про ту ж азбуку Морзе). Причому число бажано трохи менше - чим менше двійкових розрядів буде задіяно, тим ефективніше можна буде використовувати пам'ять. Ось це відповідність набору символів і чисел власне і є кодування. Бажання будь-якою ціною заощадити пам'ять, а так само роз'єднаність різних груп комп'ютерників і призвела до нинішнього стану справ. Найпоширенішим способом кодування зараз є використання для одного символу одного байта (8 біт), що визначає загальне у символів в 256. Набір перших 128 символів стандартизований (набір ASCII) і є однаковими у всіх поширених кодуваннях (ті кодування, де це не так вже практично вийшли з ужитку). Англицкий буковки і символи пунктуації знаходяться в цьому діапазоні, що і визначає їх вражаючу живучість в комп'ютерних системах :-). Інші мови знаходяться не в настільки щасливому становищі - їм усім доводиться тулитися в останніх 128 числах.

Unicode

Наприкінці 80-х багато хто усвідомив необхідність створення єдиного стандарту на кодування символів, що і призвело до появи Unicode. Unicode - це спроба раз і назавжди зафіксувати конкретне число за конкретним символом. Зрозуміло, що в 256 символів тут не укладешся при всьому бажанні. Досить довгий час здавалося, що вже 2-х то байт (65536 символів) повинно вистачити. Ан ні - остання версія стандарту Unicode (3.1) визначає вже 94140 символів. Для такого кол-ва символів, напевно, вже доведеться використовувати 4 байти (4294967296 символів). Може бути і вистачить на деякий час ... :-)

У набір символів Unicode входять всілякі літери з усякими рисками і пріпендюлькамі, грецькі, математичні, ієрогліфи, символи псевдографіки і пр. і пр. У тому числі і так улюблені нами символи кирилиці (діапазон значень 0x0400-0x04ff). Так що з цього боку ніякої дискримінації немає.

Якщо Вам цікаві конкретні коду символів, для їх перегляду зручно використовувати програму "Таблиця символів" з WinNT. Ось, наприклад, діапазон кирилиці:

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

Якщо у Вас інша OS або Вас цікавить офіційне тлумачення, то повну розкладку символів (charts) можна знайти на офіційному сайті Unicode (unicode / charts / web.html).

Типи char і byte

У Java для символів виділений окремий тип даних char розміром в 2 байти. Це часто породжує плутанину в умах початківців (особливо якщо вони раніше програмували на інших мовах, наприклад на C / C + +). Справа в тому, що в більшості інших мов для обробки символів використовуються типи даних розміром в 1 байт. Наприклад, в C / C + + тип char в більшості випадків використовується як для обробки символів, так і для обробки байтів - там немає поділу. У Java для байтів є свій тип - тип byte. Таким чином C-ішному char відповідає Java-вський byte, а Java-чортківському char зі світу C найближче тип wchar_t. Треба чітко розділяти поняття символів і байтів - інакше нерозуміння і проблеми гарантовані.

Java практично з самого свого народження використовує для кодування символів стандарт Unicode. Бібліотечні функції Java очікують побачити в змінних типу char символи, представлені кодами Unicode. В принципі, Ви, звичайно, можете запхати туди що завгодно - цифри є цифри, процесор все стерпить, але при будь-якій обробці бібліотечні функції будуть діяти виходячи з припущення що їм передали кодування Unicode. Так що можна спокійно вважати, що у типу char кодування зафіксована. Але це усередині JVM. Коли дані читаються ззовні або передаються назовні, то вони можуть бути представлені тільки одним типом - типом byte. Всі інші типи конструюються з байтів в залежності від використовуваного формату даних. Ось тут то на сцену і виходять кодування - в Java це просто формат даних для передачі символів, який використовується для формування даних типу char. Для кожної кодової сторінки в бібліотеці є по 2 класу перекодування (ByteToChar і CharToByte). Класи ці лежать в пакеті sun.io. Якщо, при перекодуванні з char в byte не було знайдено відповідного символу, він замінюється на символ?.

До речі, ці файли кодових сторінок в деяких ранніх версіях JDK 1.1 містять помилки, що викликають помилки перекодіровок, а то й взагалі виключення при виконанні. Наприклад, це стосується кодування KOI8_R. Найкраще, що можна при цьому зробити - змінити версію на більш пізню. Судячи з Sun-івської опису, більшість цих проблем було вирішено у версії JDK 1.1.6.

До появи версії JDK 1.4 набір доступних кодувань визначався тільки виробником JDK. Починаючи з 1.4 з'явилося нове API (пакет java.nio.charset), за допомогою якого Ви вже можете створити свою власну систему кодування (наприклад підтримати рідко використовувану, але моторошно необхідну саме Вам).

Клас String

У більшості випадків для подання рядків в Java використовується об'єкт типу java.lang.String. Це звичайний клас, який всередині себе зберігає масив символів (char []), і який містить багато корисних методів для маніпуляції символами. Найцікавіші - це конструктори, що мають першим параметром масив байтів (byte []) і методи getBytes (). За допомогою цих методів Ви можете виконувати перетворення з масиву байтів в рядки і назад. Для того, щоб вказати яке кодування при цьому використовувати у цих методів є строковий параметр, який задає її ім'я. Ось, наприклад, як можна виконати перекодування байтів з ЯКІ-8 в Windows-1251:

/ / Дані в кодуванні ЯКІ-8

byte [] koi8Data =. ..;

/ / Перетворимо з ЯКІ-8 в Unicode

String string = new String (koi8Data, "KOI8_R");

/ / Перетворимо з Unicode в Windows-1251

byte [] winData = string.getBytes ("Cp1251");

Список 8-ми бітових кодувань, доступних в сучасних JDK і підтримуючих російські літери Ви можете знайти нижче, в розділі "8-ми бітові кодування російських букв".

Так як кодування - це формат даних для символів, крім знайомих 8-ми бітових кодувань в Java також на рівних присутні і багатобайтові кодування. До таких відносяться UTF-8, UTF-16, Unicode і пр. Наприклад ось так можна отримати байти у форматі UnicodeLittleUnmarked (16-ти бітове кодування Unicode, молодший байт першим, без ознаки порядку байтів):

/ / Рядок Unicode

String string = "...";

/ / Перетворимо з Unicode в UnicodeLittleUnmarked

byte [] data = string.getBytes ("UnicodeLittleUnmarked");

При подібних перетвореннях легко помилитися - якщо кодування байтових даних не відповідають вказаним параметром при перетворенні з byte в char, то перекодування буде виконано неправильно. Іноді після цього можна витягнути правильні символи, але частіше за все частина даних буде безповоротно втрачена.

У реальній програмі явно вказувати кодову сторінку не завжди зручно (хоча більш надійно). Для цього була введена кодування за замовчуванням. За умовчанням вона залежить від системи та її налаштувань (для російських виндов прийнята кодування Cp1251), і в старих JDK її можна змінити установкою системного властивості file.encoding. У JDK 1.3 зміна цієї налаштування іноді спрацьовує, іноді - ні. Викликано це наступним: спочатку file.encoding ставиться з регіональних налаштувань комп'ютера. Посилання на кодування за замовчуванням запам'ятовується в нутрії при першій перетворенні. При цьому використовується file.encoding, але це перетворення відбувається ще до використання аргументів запуску JVM (собсно, при їх розборі). Взагалі-то, як стверджують в Sun, ця властивість відображає системну кодування, і вона не повинна змінюватися в командному рядку (див., наприклад, коментарі до BugID 4163515) Проте в JDK 1.4 Beta 2 зміна цієї налаштування знову почала чинити ефект. Що це, свідома зміна або побічний ефект, який може знову зникнути - Sun-вівці ясної відповіді поки не дали.

Ця кодування використовується тоді, коли явно не вказано назву сторінки. Про це треба завжди пам'ятати - Java не буде намагатися передбачити кодування байтів, які Ви передаєте для створення рядка String (так само вона не зможе прочитати Ваші думки з цього приводу :-). Вона просто використовує поточну кодування за замовчуванням. Т.к. ця настройка одна на всі перетворення, іноді можна наштовхнутися на неприємності.

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

Сторінки: 1 2 3 4 5 6 7 8
загрузка...
ur.co.ua

енциклопедія  з сиру  аджапсандалі  ананаси  узвар