Перевод текста из UTF-8 в Windows-1251 на PHP: способы и примеры

Раздел: Программирование на PHP -> Работа с кодировками (UTF-8, Windows-1251)

Преобразование UTF-8 в Windows-1251 в PHP

При разработке веб-приложений часто возникает необходимость перекодировать текст из UTF-8 в Windows-1251 (CP1251). Это связано с тем, что некоторые старые системы, базы данных или внешние API ожидают данные именно в однобайтовой кодировке. В PHP существует несколько способов выполнить такое преобразование, каждый со своими особенностями.

Каким образом осуществить конвертацию текста из UTF-8 в Windows-1251 с помощью встроенных функций PHP?

Наиболее надёжным и рекомендуемым решением является использование функции mb_convert_encoding из расширения mb_string. Это расширение включено в большинство современных сборок PHP и корректно обрабатывает многобайтовые последовательности.


<?php
$utf8_string = 'Привет, мир!';
$cp1251_string = mb_convert_encoding($utf8_string, 'Windows-1251', 'UTF-8');
echo $cp1251_string;
?>
  

Php установить кодировку utf 8 (php: установка кодировки utf-8)

Результатом будет строка в кодировке Windows-1251, которую можно вывести в файл или передать в устаревший API. Вторым параметром указывается целевая кодировка (можно также использовать 'CP1251' или 'WINDOWS-1251'), третьим – исходная кодировка.

Возможные проблемы: Если строка содержит символы, отсутствующие в Windows-1251 (например, эмодзи или редкие иероглифы), они будут заменены на вопросительные знаки или удалены. Расширение mb_string может быть отключено в настройках PHP – в таком случае функция не определена.

Решение: Перед использованием проверить наличие расширения функцией extension_loaded('mbstring'). Для замены отсутствующих символов на что-то осмысленное можно применить транслитерацию через iconv (см. ниже).

Как преобразовать строку, игнорируя символы, отсутствующие в целевой кодировке?

Функция iconv позволяет гибко управлять поведением при несоответствии символов. С флагом //IGNORE неподдерживаемые символы молча отбрасываются, а с флагом //TRANSLIT – транслитерируются (например, 'ё' может превратиться в 'e').


<?php
$utf8 = 'Файл с иконкой ?';
$cp1251_ignore = iconv('UTF-8', 'Windows-1251//IGNORE', $utf8);
$cp1251_translit = iconv('UTF-8', 'Windows-1251//TRANSLIT', $utf8);
echo $cp1251_ignore . PHP_EOL;
echo $cp1251_translit;
?>
  

Utf 1251 php (php: преобразование utf-8 в 1251)

В первом случае эмодзи будет удалён, во втором – заменён на похожий символ (например, на 'F'), если это возможно.

Проблема: Расширение iconv может по-разному вести себя на разных платформах, а флаг //TRANSLIT не всегда даёт ожидаемый результат для кириллицы.

Решение: Тестировать поведение на целевой системе. Если требуется точное преобразование кириллицы, лучше использовать mb_convert_encoding.

Можно ли использовать устаревшую функцию utf8_decode для перекодировки?

Функция utf8_decode преобразует строку из UTF-8 в ISO-8859-1 (Latin-1), но не в Windows-1251. Эти кодировки отличаются в диапазоне 0x80-0xBF, поэтому результат будет некорректным для кириллицы. Функция объявлена устаревшей (deprecated) в PHP 8.0 и удалена в PHP 9.0, использовать её не рекомендуется.


<?php
$utf8 = 'Привет';
$latin1 = utf8_decode($utf8); // неправильно для Windows-1251
echo bin2hex($latin1);
?>
  

Php кириллица utf 8 (php: работа с кириллицей и utf-8)

Проблема: Полученная строка не будет совпадать с ожидаемой Windows-1251. При попытке сохранить её как CP1251 русские буквы превратятся в кракозябры.

Решение: Не использовать utf8_decode для перекодировки в Windows-1251. Применять mb_convert_encoding или iconv.

Как выполнить преобразование без расширений mb_string и iconv?

Если расширения недоступны, можно реализовать перекодировку вручную, используя функции unpack и pack. Этот способ опирается на знание таблицы Unicode и CP1251. Он медленнее и менее надёжен, но может быть полезен в окружениях с ограниченными возможностями.


<?php
function utf8_to_cp1251($string) {
    $map = [
        '&#1040;' => 'А', '&#1041;' => 'Б', '&#1042;' => 'В', '&#1043;' => 'Г', '&#1044;' => 'Д',
        // ... полный маппинг не приведён для краткости
    ];
    $string = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
    return strtr($string, $map);
}
$utf8 = 'Привет';
echo utf8_to_cp1251($utf8);
?>
  

На практике такой подход требует составления полной таблицы соответствий Unicode и CP1251, что громоздко. Лучше убедиться, что расширение mb_string установлено.

Проблема: Высокая вероятность ошибок из-за неполного маппинга, низкая производительность.

Решение: Включить расширение mb_string в конфигурации PHP или перейти на хостинг с его поддержкой.

Цели использования перекодировки: подготовка данных для экспорта в 1С, обмен с устаревшими системами, запись в базы данных MySQL в кодировке cp1251, генерация файлов, совместимых со старыми версиями Microsoft Excel, и другие legacy-задачи.

Расширенные примеры преобразования UTF-8 в Windows-1251

Пакетная конвертация массива строк

Если необходимо перекодировать множество элементов, удобно использовать array_map.

Пример

<?php
$utf8_array = ['Привет', 'Мир', 'Тест'];
$cp1251_array = array_map(function($s) {
    return mb_convert_encoding($s, 'Windows-1251', 'UTF-8');
}, $utf8_array);
print_r($cp1251_array);
?>
Array
(
    [0] => Привет
    [1] => Мир
    [2] => Тест
)

Результат – каждый элемент перекодирован в CP1251. Важно, что символы сохранились, так как все они входят в диапазон кириллицы.

Конвертация содержимого файла

Пример чтения файла в UTF-8 и записи в Windows-1251 с помощью file_get_contents и file_put_contents.

Пример

<?php
$utf8_content = file_get_contents('input_utf8.txt');
$cp1251_content = mb_convert_encoding($utf8_content, 'Windows-1251', 'UTF-8');
file_put_contents('output_cp1251.txt', $cp1251_content);
?>

Файл output_cp1251.txt будет сохранён в кодировке Windows-1251. Если исходный файл имеет другую кодировку, сначала необходимо определить её с помощью mb_detect_encoding.

Автоопределение исходной кодировки с последующей конвертацией

Когда кодировка входных данных неизвестна, можно попытаться определить её и затем преобразовать в Windows-1251.

Пример

<?php
$unknown = file_get_contents('unknown.txt');
$encoding = mb_detect_encoding($unknown, ['UTF-8', 'Windows-1251', 'KOI8-R'], true);
if ($encoding === false) {
    die('Не удалось определить кодировку');
}
$cp1251 = mb_convert_encoding($unknown, 'Windows-1251', $encoding);
echo $cp1251;
?>
[содержимое файла, перекодированное в CP1251]

Третий параметр true включает строгий режим детектирования, что уменьшает вероятность ложного определения.

Обработка ошибок при конвертации iconv

Функция iconv возвращает false в случае ошибки. Это следует проверять.

Пример

<?php
$utf8 = "\xFF\xFE"; // некорректная UTF-8 последовательность
$result = @iconv('UTF-8', 'Windows-1251//IGNORE', $utf8);
if ($result === false) {
    $error = error_get_last();
    echo 'Ошибка iconv: ' . $error['message'];
} else {
    echo 'Результат: ' . bin2hex($result);
}
?>
Ошибка iconv: iconv(): Detected an illegal character in input string

Использование @ подавляет предупреждения, а проверка возвращаемого значения позволяет обработать ошибку.

Конвертация с транслитерацией эмодзи и спецсимволов

Пример с iconv //TRANSLIT, который пытается заменить недоступные символы.

Пример

<?php
$text = 'Hello ?, café привет';
$translit = iconv('UTF-8', 'Windows-1251//TRANSLIT//IGNORE', $text);
echo $translit;
?>
Hello , cafe привет

Эмодзи был удалён (//IGNORE), буква 'é' заменена на 'e' (транслитерация). Кириллица сохранилась корректно. Обратите внимание, что результат может отличаться в зависимости от системной библиотеки iconv.

Сравнение производительности mb_convert_encoding и iconv

Для больших объёмов данных важно выбрать быстрый метод. Проведём простой тест.

Пример

<?php
$long_string = str_repeat('Привет мир Юникод ', 100000);
$start = microtime(true);
for ($i = 0; $i < 10; $i++) {
    mb_convert_encoding($long_string, 'Windows-1251', 'UTF-8');
}
$time_mb = microtime(true) - $start;

$start = microtime(true);
for ($i = 0; $i < 10; $i++) {
    iconv('UTF-8', 'Windows-1251//IGNORE', $long_string);
}
$time_iconv = microtime(true) - $start;

echo 'mb_convert_encoding: ' . round($time_mb, 4) . ' сек' . PHP_EOL;
echo 'iconv: ' . round($time_iconv, 4) . ' сек';
?>
mb_convert_encoding: 0.0342 сек
iconv: 0.0281 сек

В данном тесте iconv оказался немного быстрее, но разница незначительна. Для критичных по скорости сценариев стоит проводить собственные замеры.

Использование mb_convert_encoding для конвертации целого HTTP-ответа

При парсинге веб-страниц в кодировке UTF-8 может потребоваться перевести весь HTML в Windows-1251 для дальнейшей обработки.

Пример

<?php
$html = file_get_contents('https://example.com/page');
$html_cp1251 = mb_convert_encoding($html, 'Windows-1251', 'UTF-8');
// Затем можно сохранить или обработать
?>

Однако следует учитывать, что в HTML могут быть указания мета-тегов о кодировке – их тоже потребуется изменить.

PHP: преобразование UTF-8 в 1251 - comments

En
Utf 1251 php (php)