Перекодировка cp1251 в UTF8

Сегодня столкнулся с проблемой перекодировки русского текста из cp1251 (windows-1251) в UTF8. Решение нашел быстро. Как всегда нельзя переоценить роль Google;)

Ранее пользовался iconv(“CP1251”, “UTF-8”, $text_for_convert), но, как известно iconv даёт большую нагрузку на сервер и работает медленнее чем представленная ниже функция.

function cp1251_to_utf8 ($txt)  {
    $in_arr = array (
        chr(208), chr(192), chr(193), chr(194),
        chr(195), chr(196), chr(197), chr(168),
        chr(198), chr(199), chr(200), chr(201),
        chr(202), chr(203), chr(204), chr(205),
        chr(206), chr(207), chr(209), chr(210),
        chr(211), chr(212), chr(213), chr(214),
        chr(215), chr(216), chr(217), chr(218),
        chr(219), chr(220), chr(221), chr(222),
        chr(223), chr(224), chr(225), chr(226),
        chr(227), chr(228), chr(229), chr(184),
        chr(230), chr(231), chr(232), chr(233),
        chr(234), chr(235), chr(236), chr(237),
        chr(238), chr(239), chr(240), chr(241),
        chr(242), chr(243), chr(244), chr(245),
        chr(246), chr(247), chr(248), chr(249),
        chr(250), chr(251), chr(252), chr(253),
        chr(254), chr(255)
    );   

    $out_arr = array (
        chr(208).chr(160), chr(208).chr(144), chr(208).chr(145),
        chr(208).chr(146), chr(208).chr(147), chr(208).chr(148),
        chr(208).chr(149), chr(208).chr(129), chr(208).chr(150),
        chr(208).chr(151), chr(208).chr(152), chr(208).chr(153),
        chr(208).chr(154), chr(208).chr(155), chr(208).chr(156),
        chr(208).chr(157), chr(208).chr(158), chr(208).chr(159),
        chr(208).chr(161), chr(208).chr(162), chr(208).chr(163),
        chr(208).chr(164), chr(208).chr(165), chr(208).chr(166),
        chr(208).chr(167), chr(208).chr(168), chr(208).chr(169),
        chr(208).chr(170), chr(208).chr(171), chr(208).chr(172),
        chr(208).chr(173), chr(208).chr(174), chr(208).chr(175),
        chr(208).chr(176), chr(208).chr(177), chr(208).chr(178),
        chr(208).chr(179), chr(208).chr(180), chr(208).chr(181),
        chr(209).chr(145), chr(208).chr(182), chr(208).chr(183),
        chr(208).chr(184), chr(208).chr(185), chr(208).chr(186),
        chr(208).chr(187), chr(208).chr(188), chr(208).chr(189),
        chr(208).chr(190), chr(208).chr(191), chr(209).chr(128),
        chr(209).chr(129), chr(209).chr(130), chr(209).chr(131),
        chr(209).chr(132), chr(209).chr(133), chr(209).chr(134),
        chr(209).chr(135), chr(209).chr(136), chr(209).chr(137),
        chr(209).chr(138), chr(209).chr(139), chr(209).chr(140),
        chr(209).chr(141), chr(209).chr(142), chr(209).chr(143)
    );   

    $txt = str_replace($in_arr,$out_arr,$txt);
    return $txt;
}

Отказаться от iconv вынудило еще то, что в определенный момент при перекодировании из windows-1251 в UTF-8 без видимых причин, данная функция стала возвращать пустую строку.

З.Ы. Если поменять местами $in_arr и $out_arr, то функция заработает “в обратном направлении”, т.е. будет преобразовывать UTF-8 в CP-1251.

24 Responses to “Перекодировка cp1251 в UTF8”

  1. Demroos says:

    Большое спасибо за функцию!!!
    Реально выручил!

  2. 755 says:

    Спасибо огромное)
    Очень помогло)) iconv нереально глючная(

  3. toorr2p says:

    У меня такая проблема… на сайте есть регистрация, и если пользователь регистрируясь указывает в логине или пароле русские символы, то при авторизации (когда из БД вытаскивается логин и пароль) происходит ошибка – пользователь не может зайти на сайт!!! MySQL база работает под UTF-8 может ли это быть из-за кодировки? И могу ли я испраить это с помощю вашего скрипта, и ели да то как? Это мне перед заносом в БД нужно переменные из формы перекодировать вот так: function cp1251_to_utf8 ($login) {
    $in_arr = array (…

  4. Mihalytch says:

    Если текст на вашем сайте выводится в кодировке cp-1251, то перекодировка полученных от пользователя данных должна помочь.
    Еще попробуйте сразу после коннекта с базой выполнить:
    mysql_query(“SET NAMES ‘CP-1251′”);
    Думаю, тогда можно будет обойтись без перекодировки.

  5. Alex says:

    Отличная функция, спасибо. Но здесь представлен только русский язык, мне еще нужно добавить буквы украинского алфавита, например “і”, “є”, “ї”.

    Как узнать их код, чтобы записать во второй массив? В первый я их записываю с помощью функции ord()

    Спасибо

  6. taxa says:

    шестнадцатиричный код можно узнать в Word’е:
    после символа нажать Alt+X и символ измениться на код.

    кстати, я использую немного другой вариант данной функции:
    видете, что в первом массиве код 208 стоит самым первым(?!) это потому, что если его поставить позже, то он сначала навставляет 208 в результат, а потом попортит НОРМАЛЬНЫЙ перевод ко всем бабушкам… поэтому для новых символов я пошел другим путём
    в верхний массив добавляю код, а в нижний уникод… лучше на примере:

    chr(194), chr(185), chr(176),
    chr(195), chr(196), chr(151), chr(150),
    chr(171), chr(187), chr(222),

    соответствует

    chr(208).chr(146), ‘№’, ‘°’,
    chr(208).chr(147), chr(208).chr(148), ‘—’,chr(0).chr(45),
    ‘«’,’»’, ‘Ю’,

    примечание: тут код десятичный, поэтому надо ещё через calc код пересчитать

    а в целом ОГРОМНОЕ СПАСИБО! 🙂

  7. taxa says:

    млииин, эксплорер с чистой совестью мой код съел и в буквы превратил… :-))

    повторю вторую часть навставляв пробелов между &# и кодом

    chr(208).chr(146), ‘&# 8470;’, ‘&# 0176;’,
    chr(208).chr(147), chr(208).chr(148), ‘&# 8212;’, chr(0).chr(45),
    ‘&# 0171;’,’&# 0187;’, ‘&# 1070;’,

  8. Mihalytch says:

    Спасибо! Сегодня обновлю обновлю статью!

  9. tiger-nick says:

    Моно попробовать вот так (в целях уменьшения кода):
    function UTF8Decode($cp1251){
    $utf8=”;
    for($i=0;$i= 240 && $c <= 255) $utf8.=chr(209).chr($c-48);
    elseif(($c=192)||$c==168) $utf8.=chr(208).chr($c-112);
    }
    return $utf8;
    }

  10. tiger-nick says:

    >>> Моно попробовать вот так (в целях уменьшения кода)
    Это тот-же код, только не на массивах

  11. tiger-nick says:

    Полностью поправил, вот исходник:
    function UTF8Decode($cp1251){
    $utf8=””;
    for($i=0;$i191&&$c239&&$c<256)$utf8.=chr(209).chr($c-112);
    else $utf8.=$cp1251[$i];
    }
    return $utf8;
    }

  12. DeVS says:

    Спасибо. Очень помогло.

  13. VICTOR_81 says:

    tiger-nick
    странная последняя функция
    function UTF8Decode($cp1251){

    php Говорит ошибка syntax error, unexpected ‘)’, expecting ‘;’ в строке for($i=0;$i191&&$c239&&$c<256)$utf8.=chr(209).chr($c-112);
    может я чего то не понимаю, а else у вас к чему привязанно?

  14. leomichao says:

    Чтобы вытащить описания книг из FB2, которые в UTF8,
    воспользовался этой функцией. Громоздко, но всегда
    можно вставить дополнительные сочетания символов.
    Функция на фоксе, но это не важно.
    FUNCTION UTF8TOCP1251
    PARAMETERS _TXT

    DECLARE MA[69,2]
    MA[01,1]=”Рђ” && А
    MA[02,1]=”Р‘'” && Б
    MA[03,1]=”Р’” && В
    MA[04,1]=CHR(208)+CHR(147) && Г Р“
    MA[05,1]=CHR(208)+CHR(148) && Д Р”
    MA[06,1]=”Р•” && Е
    MA[07,1]=”РЃ” && Ё
    MA[08,1]=”Р–” && Ж
    MA[09,1]=”Р—” && З
    MA[10,1]=”Рљ” && К
    MA[11,1]=”И” && И
    MA[12,1]=”Р™” && Й
    MA[13,1]=”Р›” && Л
    MA[14,1]=”Рњ” && М
    MA[15,1]=”Рќ” && Н
    MA[16,1]=”Рћ” && О
    MA[17,1]=”Рџ” && П
    MA[18,1]=”Р ” && Р
    MA[19,1]=”РЎ” && С
    MA[20,1]=”Рў” && Т
    MA[21,1]=”РЈ” && У
    MA[22,1]=”Р¤” && Ф
    MA[23,1]=”РҐ” && Х
    MA[24,1]=”Р¦” && Ц
    MA[25,1]=”Р§” && Ч
    MA[26,1]=”Р­” && Э
    MA[27,1]=”РЁ” && Ш
    MA[28,1]=”Р©” && Щ
    MA[29,1]=”Р®” && Ю
    MA[30,1]=”Р«” && Ы
    MA[31,1]=”Р¬” && Ь
    MA[32,1]=”РЄ” && Ъ
    MA[33,1]=”РЇ” && Я
    MA[34,1]=”Р°” && а
    MA[35,1]=”Р±” && б
    MA[36,1]=”РІ” && в
    MA[37,1]=”Рі” && г
    MA[38,1]=”Рґ” && д
    MA[39,1]=”Рµ” && е
    MA[40,1]=”С‘” && ё
    MA[41,1]=”Р¶” && ж
    MA[42,1]=”Р·” && з
    MA[43,1]=”Рё” && и
    MA[44,1]=”Р№” && й
    MA[45,1]=”Рє” && к
    MA[46,1]=”Р»” && л
    MA[47,1]=”Рј” && м
    MA[48,1]=”РЅ” && н
    MA[49,1]=”Рѕ” && о
    MA[50,1]=”Рї” && п
    MA[51,1]=”СЂ” && р
    MA[52,1]=”СЃ” && с
    MA[53,1]=”С‚” && т
    MA[54,1]=”Сѓ” && у
    MA[55,1]=’С„’ && ф
    MA[56,1]=”С…” && х
    MA[57,1]=”С†” && ц
    MA[58,1]=”С‡” && ч
    MA[59,1]=”СЌ” && э
    MA[60,1]=”С€” && ш
    MA[61,1]=”С‰” && щ
    MA[62,1]=”СЋ” && ю
    MA[63,1]=”С‹” && ы
    MA[64,1]=”СЊ” && ь
    MA[65,1]=”СЉ” && ъ
    MA[66,1]=”СЏ” && я
    MA[67,1]=’–’ && –
    MA[68,1]=’ – ‘ && –  –
    MA[69,1]=”— &&CHR(194) && – В
    ********************
    MA[01,2]=”А”
    MA[02,2]=”Б”
    MA[03,2]=”В”
    MA[04,2]=”Г”
    MA[05,2]=”Д”
    MA[06,2]=”Е”
    MA[07,2]=”Ё”
    MA[08,2]=”Ж”
    MA[09,2]=”З”
    MA[10,2]=”К”
    MA[11,2]=”И”
    MA[12,2]=”Й”
    MA[13,2]=”Л”
    MA[14,2]=”М”
    MA[15,2]=”Н”
    MA[16,2]=”О”
    MA[17,2]=”П”
    MA[18,2]=”Р”
    MA[19,2]=”С”
    MA[20,2]=”Т”
    MA[21,2]=”У”
    MA[22,2]=”Ф”
    MA[23,2]=”Х”
    MA[24,2]=”Ц”
    MA[25,2]=”Ч”
    MA[26,2]=”Э”
    MA[27,2]=”Ш”
    MA[28,2]=”Щ”
    MA[29,2]=”Ю”
    MA[30,2]=”Ы”
    MA[31,2]=”Ь”
    MA[32,2]=”Ъ”
    MA[33,2]=”Я”
    MA[34,2]=”а”
    MA[35,2]=”б”
    MA[36,2]=”в”
    MA[37,2]=”г”
    MA[38,2]=”д”
    MA[39,2]=”е”
    MA[40,2]=”ё”
    MA[41,2]=”ж”
    MA[42,2]=”з”
    MA[43,2]=”и”
    MA[44,2]=”й”
    MA[45,2]=”к”
    MA[46,2]=”л”
    MA[47,2]=”м”
    MA[48,2]=”н”
    MA[49,2]=”о”
    MA[50,2]=”п”
    MA[51,2]=”р”
    MA[52,2]=”с”
    MA[53,2]=”т”
    MA[54,2]=”у”
    MA[55,2]=”ф”
    MA[56,2]=”х”
    MA[57,2]=”ц”
    MA[58,2]=”ч”
    MA[59,2]=”э”
    MA[60,2]=”ш”
    MA[61,2]=”щ”
    MA[62,2]=”ю”
    MA[63,2]=”ы”
    MA[64,2]=”ь”
    MA[65,2]=”ъ”
    MA[66,2]=”я”
    MA[67,2]=”- ”
    MA[68,2]=” – ”
    MA[69,2]=”…”
    FOR I=1 TO 69
    _TXT= STRTRAN( _TXT, MA[I,1], MA[I,2] )
    ENDFOR
    RETURN _TXT

  15. Павел says:

    Для украинских символов коды:
    Маленькое “и”: і – 0456
    Большое “И: І – 0406
    Маленькое “е”: є – 0454
    Большое “Е”: Є – 0404
    Маленькое “йи”: ї – 0457
    Большое “ИЙ”: Ї – 0407

  16. Дмитрий says:

    Спасибо… все мозги себе откомпостировал… iconv стал возвращать пустую строку(( теперь все ок))

  17. maxim says:

    Спасибо за функцию

  18. oblomov says:

    Спасибо. Функция рулит.

  19. keks keksov says:

    Что бы не ломать голову о порядке следования подстановок для str_replace нужно использовать strtr
    Для примера, я добавил знак Номер- №
    Word выдает какие-то не те цифры, скажем для того же символа “номер” он сообщает нам x2116, а на самом деле это xE28496. Правильные цифры выдает notepad++ – создаем новый документ UTF-8 без BOM, печатаем нужную букву и потом смотрим файл в hex виде (можно в тотал командере по F3 и потом перейти в hex режим, нажав 3 (или в меню)

    class TConv
    {
    // таблицы символов, см. конец этого файла
    static $CP1251;
    static $UTF8;
    static $WIN2UTF_TABLE = false;

    static function win2utf ( $aString )
    { // http://mihalytch.org.ua/programming/php/convert-cp1251-utf8.html
    if ( !self::$WIN2UTF_TABLE )
    self::$WIN2UTF_TABLE = array_combine( self::$CP1251, self::$UTF8 );

    $Result = strtr( $aString, self::$WIN2UTF_TABLE );
    return $Result;
    }
    }

    TConv::$CP1251 = array (

    chr(208), // CAPITALL ER
    chr(185), // NUMERO SIGN
    chr(192), chr(193), chr(194),
    chr(195), chr(196), chr(197), chr(168),
    chr(198), chr(199), chr(200), chr(201),
    chr(202), chr(203), chr(204), chr(205),
    chr(206), chr(207), chr(209), chr(210),
    chr(211), chr(212), chr(213), chr(214),
    chr(215), chr(216), chr(217), chr(218),
    chr(219), chr(220), chr(221), chr(222),
    chr(223), chr(224), chr(225), chr(226),
    chr(227), chr(228), chr(229), chr(184),
    chr(230), chr(231), chr(232), chr(233),
    chr(234), chr(235), chr(236), chr(237),
    chr(238), chr(239), chr(240), chr(241),
    chr(242), chr(243), chr(244), chr(245),
    chr(246), chr(247), chr(248), chr(249),
    chr(250), chr(251), chr(252), chr(253),
    chr(254), chr(255)

    );

    TConv::$UTF8 = array (
    chr(208).chr(160), // // CAPITALL ER
    chr(226).chr(132).chr(150), // NUMERO SIGN
    chr(208).chr(144), chr(208).chr(145), chr(208).chr(146),
    chr(208).chr(147), chr(208).chr(148),
    chr(208).chr(149), chr(208).chr(129), chr(208).chr(150),
    chr(208).chr(151), chr(208).chr(152), chr(208).chr(153),
    chr(208).chr(154), chr(208).chr(155), chr(208).chr(156),
    chr(208).chr(157), chr(208).chr(158), chr(208).chr(159),
    chr(208).chr(161), chr(208).chr(162), chr(208).chr(163),
    chr(208).chr(164), chr(208).chr(165), chr(208).chr(166),
    chr(208).chr(167), chr(208).chr(168), chr(208).chr(169),
    chr(208).chr(170), chr(208).chr(171), chr(208).chr(172),
    chr(208).chr(173), chr(208).chr(174), chr(208).chr(175),
    chr(208).chr(176), chr(208).chr(177), chr(208).chr(178),
    chr(208).chr(179), chr(208).chr(180), chr(208).chr(181),
    chr(209).chr(145), chr(208).chr(182), chr(208).chr(183),
    chr(208).chr(184), chr(208).chr(185), chr(208).chr(186),
    chr(208).chr(187), chr(208).chr(188), chr(208).chr(189),
    chr(208).chr(190), chr(208).chr(191), chr(209).chr(128),
    chr(209).chr(129), chr(209).chr(130), chr(209).chr(131),
    chr(209).chr(132), chr(209).chr(133), chr(209).chr(134),
    chr(209).chr(135), chr(209).chr(136), chr(209).chr(137),
    chr(209).chr(138), chr(209).chr(139), chr(209).chr(140),
    chr(209).chr(141), chr(209).chr(142), chr(209).chr(143)
    );

  20. keks keksov says:

    Разобрался с кодировками, Word все правильно показывает, только это не UTF-8, а UNICODE
    Правила преобразования UNICODE в UTF-8 можно глянуть тут http://en.wikipedia.org/wiki/UTF-8
    Итак, для нашей буквы “Номер” UNICODE значение 2116 (Hex)
    Оно подпадает под правило U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
    При помощи calc преобразуем 2116 (Hex) в двоичный вид 10000100010110 (Bin)
    Вставлеям наши биты в маску
    U+FFFF 1110[0010] 10[000100] 10[010110]
    Полученное число запихиваем снова в calc 111000101000010010010110 и получаем E28496 hex,
    это и есть искомый код нашего символа в UTF-8
    Его можно записать в виде chr(0xE2).chr(0x84).chr(0x96) не преобразуя в Dec

    UNICODE таблицы можно брать вот тут http://www.unicode.org/charts
    В частности, наш многострадальный символ “Номер” находится вот в этом документе
    http://www.unicode.org/charts/PDF/U2100.pdf
    Вот кириллические символы http://www.unicode.org/charts/PDF/U0400.pdf

  21. Дмитрий says:

    Пасиба, действительно помогла!!!

  22. Павел says:

    Огромнейшее спасибо!От всего сердца)

  23. lazorg says:

    Спасибо, функиця очень пригодилась)

  24. m1zh0ry says:

    Спасибо, очень выручили сделал перевод в utf8 и из большое спасибо!!

Leave a Reply




*