Как перекодировать latin1 в кириллицу

Как перекодировать latin1 в кириллицу

Пишу данную заметку просто потому, что достало. Мне каждый раз задают один и тот же вопрос, спрашивают об одном и том же: “Как перекодировать кракозябры из базы данных, хранящей строки в кодировке latin1 в нормальную кириллицу (windows-1251) или utf-8”.

Во-первых, я никому не рекомендую продолжать работать в кодировке windows-1251. Эта однобайтовая кодировка уже не удовлетворяет требованиям современности. Поскорее переводите все проекты на utf-8. Чем быстрее это будет сделано, тем быстрее пропадут у вас проблемы с кракозябрами.

Теперь о latin1. Эта кодировка (также известна как windows-1252) повсеместно использовалась ранее в MySQL вплоть до версии 4. Символьная таблица кириллических букв находится в ней на месте арабских символов. Но поскольку она тоже однобайтовая, то при чтении данных в этой кодировке из этой таблицы и выводе их как windows-1251 не возникает никаких проблем, ведь коды в итоге те же самые. Но всё это будет работать только до тех пор, пока вы не установите MySQL 5+, работающий по дефолту в utf-8.

Что же делает MySQL 5+, передавая Вам такие данные ? Перед передачей на сторону клиента он честно перекодирует все данные в utf-8, помещая арабские символы (а в latin1 ваша кириллица на самом деле является арабскими символами) в тот диапазон кодов utf-8, где они и должны быть. В результате если вы даже попытаетесь перекодировать полученную utf-8-строку обратно в кириллицу функцией iconv(‘utf-8’, ‘windows-1251’, $str), то у вас ничего не получится. iconv выдаст ошибку, либо вернёт пустую строку.

Первое, что делает программист – он пытается изменить кодировку таблицы latin1 на windows-1251 в phpMyAdmin. Но MySQL этого сделать не может, ведь в кодировке windows-1251 нет соответствующих арабских символов. Второе, что приходит в голову – сконвертировать эту таблицу в utf-8. И это получается. Только вот тексты по-прежнему отображаются кракозябрами.

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

Решение тут довольно простое, но чтобы к нему прийти самостоятельно, надо чётко понимать – что такое кодировки и как они работают. В понимании помогут мои hand-made диаграммы.

А вот и алгоритм, которым я пользуюсь, чтобы привести кодировки в порядок.

1. Перевожу все таблицы БД в кодировку utf-8. При этом якобы кириллические символы, хранящиеся в кодировке latin1, а поэтому на самом деле являющиеся арабскими, переводятся в utf-8 и занимают свои законные места в диапазоне кодов utf-8, предназначенном для арабских символов.
2. Пишу микроутилиту на PHP, которая делает следующее с каждой символьной строкой:
а) Переводит строку в кодировку windows-1252. Тут проблем быть не должно. Тем самым арабские буквы занимают диапазон кодов A0-FF.
б) Переводит полученную однобайтовую строку в utf-8, но уже не как windows-1252, а как windows-1251, т.е. выдавая символы из диапазона A0-FF за кириллические. В итоге символы попадают в utf-8 в тот диапазон кодов, который предназначен для кириллических символов.
3. Всё, теперь наша строка официально является кириллической строкой в utf-8. Её можно записать обратно в ту же ячейку БД, либо сразу выдать в выходной поток. Однако я всё же рекомендую выполнить однократное полное преобразование БД, и забыть о latin1 как о страшном сне.

Ниже привожу сэмпл кода на PHP, который переводит ФИО пользователей в нормальную кириллическую кодировку.

$q = ‘select id, fio from `users`’;
$res = mysql_query($q);
while (($row = mysql_fetch_assoc($res)) !== false) {
// Преобразуем fio из utf-8/latin1 в windows-1252
$s = iconv(‘utf-8’, ‘windows-1252’, $row[‘fio’]);
// Преобразуем строку из однобайтной кодировки обратно в utf-8, выдав её за windows-1251
$s = iconv(‘windows-1251’, ‘utf-8’, $s);
// Сохраняем назад в БД
$q = ‘update `users` set fio = “‘.addslashes($s).'” where id = ‘.$row[‘id’];
mysql_query($q);
}

0 0 votes
Рейтинг статьи
Поделитесь публикацией

Share this post

Subscribe
Уведомлять
0 комментариев
Inline Feedbacks
View all comments