Как выполнить перекодировку файлов в PHP - полное руководство

Раздел: Обработка данных в PHP -> Работа со строками и текстом

Преобразование кодировки текстового файла в PHP

При работе с текстовыми файлами часто возникает необходимость изменить кодировку их содержимого. Например, файл получен в Windows-1251, а проект требует UTF-8. В PHP существует несколько способов выполнения перекодировки, каждый из которых подходит для разных сценариев.

Как выполнить перекодировку файла с помощью mb_convert_encoding?

Самый универсальный и рекомендуемый подход - использование функций модуля mbstring. Метод mb_convert_encoding позволяет преобразовать строку из одной кодировки в другую. Для работы с файлом его содержимое сначала читается в переменную, затем перекодируется и записывается обратно.


<?php
// Чтение содержимого файла
$inputFile = 'input.txt';
$content = file_get_contents($inputFile);
if ($content === false) {
    die('Ошибка чтения файла');
}

// Перекодировка из Windows-1251 в UTF-8
$converted = mb_convert_encoding($content, 'UTF-8', 'Windows-1251');
if ($converted === false) {
    die('Ошибка перекодировки');
}

// Запись результата в новый файл
$outputFile = 'output.txt';
if (file_put_contents($outputFile, $converted) === false) {
    die('Ошибка записи файла');
}
echo 'Файл успешно перекодирован';
?>

Параметры mb_convert_encoding: целевая кодировка, то, что перекодируется, и исходная кодировка. Если исходная кодировка не указана, функция попытается определить её автоматически, но это ненадёжно.

Типичная ошибка: отсутствие модуля mbstring приводит к ошибке вызова функции. Решение - установить или включить расширение в php.ini.

Другая проблема: неверное указание исходной кодировки приводит к кракозябрам. Рекомендуется точно знать кодировку входного файла или использовать функцию mb_detect_encoding для предварительного анализа.

Как перекодировать файл с помощью iconv?

Функция iconv из расширения iconv также выполняет конвертацию кодировок. Она может быть доступна в окружениях без mbstring.


<?php
$content = file_get_contents('input.txt');
// iconv(исходная, целевая, строка)
$converted = iconv('Windows-1251', 'UTF-8//IGNORE', $content);
if ($converted === false) {
    die('Ошибка iconv');
}
file_put_contents('output.txt', $converted);
echo 'Готово';
?>

Суффикс //IGNORE отбрасывает символы, которые невозможно преобразовать. Альтернатива - //TRANSLIT для транслитерации.

Ошибка: iconv() может отказать при преобразовании с неподдерживаемыми кодировками. Решение - проверить список поддерживаемых кодировок через iconv_get_encoding().

Как автоматически определить кодировку файла и перекодировать?

Если исходная кодировка неизвестна, применяют mb_detect_encoding с последующей конвертацией.


<?php
$content = file_get_contents('input.txt');
$enc = mb_detect_encoding($content, ['UTF-8', 'Windows-1251', 'KOI8-R', 'ISO-8859-5'], true);
if ($enc === false) {
    die('Кодировка не определена');
}
$converted = mb_convert_encoding($content, 'UTF-8', $enc);
file_put_contents('output.txt', $converted);
echo 'Определена кодировка: ' . $enc;
?>

Третий параметр strict (true) повышает точность, но может не определить некоторые кодировки.

Проблема: детектор может ошибаться на коротких или смешанных текстах. Рекомендуется использовать список возможных кодировок и проверять результат визуально.

Как перекодировать файл построчно для экономии памяти?

При работе с большими файлами нецелесообразно загружать весь файл в память. Можно читать и обрабатывать файл построчно.


<?php
$in = fopen('большой.txt', 'r');
$out = fopen('большой_utf8.txt', 'w');
if (!$in || !$out) die('Ошибка открытия файлов');
while (($line = fgets($in)) !== false) {
    $converted = mb_convert_encoding($line, 'UTF-8', 'Windows-1251');
    fwrite($out, $converted);
}
fclose($in); fclose($out);
echo 'Готово';
?>

Такой подход снижает потребление памяти, но работает дольше из-за множества операций ввода/вывода.

Ошибка: при записи в файл в кодировке UTF-8 может потребоваться добавить BOM в начало. По умолчанию BOM не добавляется. Если нужен BOM, запишите его первой строкой: fwrite($out, "\xEF\xBB\xBF");.

Как закодировать содержимое файла в base64 для передачи?

Для передачи бинарных данных по текстовым протоколам (например, JSON) применяют кодирование base64.


<?php
$binary = file_get_contents('image.png');
$base64 = base64_encode($binary);
file_put_contents('image_base64.txt', $base64);
echo 'Закодировано';
?>

Обратное декодирование: file_put_contents('image.png', base64_decode(file_get_contents('image_base64.txt')));

Проблема: base64 увеличивает размер данных на 33%. Для больших файлов это может быть критично. Решение - сжимать данные перед кодированием (например, через gzcompress).

Расширенные примеры перекодировки файлов

Пример 1. Перекодировка с проверкой успешности каждого шага

Пример

<?php
function convertFile($src, $dst, $from, $to) {
    if (!file_exists($src)) return 'Исходный файл не найден';
    $content = file_get_contents($src);
    if ($content === false) return 'Не удалось прочитать файл';
    $converted = mb_convert_encoding($content, $to, $from);
    if ($converted === false) return 'Ошибка конвертации';
    if (file_put_contents($dst, $converted) === false) return 'Ошибка записи';
    return true;
}
$result = convertFile('data.txt', 'data_utf8.txt', 'Windows-1251', 'UTF-8');
if ($result === true) echo 'Успех';
else echo 'Ошибка: ' . $result;
?>
Успех

Пример 2. Обработка файла с неизвестной кодировкой и сохранение в UTF-8

Пример

<?php
$source = 'mystery.txt';
$content = file_get_contents($source);
$candidates = ['UTF-8', 'Windows-1251', 'KOI8-R', 'ISO-8859-5', 'BIG5'];
$enc = mb_detect_encoding($content, $candidates, true);
if (!$enc) {
    // Попробуем широкий список
    $enc = mb_detect_encoding($content, mb_list_encodings(), true);
}
if (!$enc) die('Не удалось определить кодировку');
echo 'Обнаружена: ' . $enc . PHP_EOL;
$utf8 = mb_convert_encoding($content, 'UTF-8', $enc);
file_put_contents('converted_utf8.txt', $utf8);
?>
Обнаружена: Windows-1251

Пример 3. Перекодировка CSV файла с учётом разделителей

Пример

<?php
$in = fopen('data.csv', 'r');
$out = fopen('data_utf8.csv', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF)); // BOM для UTF-8
while (($row = fgetcsv($in, 0, ';')) !== false) {
    $newRow = [];
    foreach ($row as $cell) {
        $newRow[] = mb_convert_encoding($cell, 'UTF-8', 'Windows-1251');
    }
    fputcsv($out, $newRow, ';');
}
fclose($in); fclose($out);
echo 'CSV перекодирован';
?>
CSV перекодирован

Пример 4. Кодирование бинарного файла в base64 с URL-безопасным вариантом

Пример

<?php
$data = file_get_contents('photo.jpg');
$b64 = base64_encode($data);
// URL-безопасная версия: замена + на - и / на _
$urlSafe = rtrim(strtr($b64, '+/', '-_'), '=');
echo 'URL-safe base64: ' . substr($urlSafe, 0, 50) . '...';
?>
URL-safe base64: /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAA... (сокращено)

Пример 5. Конвертация большого файла через временный буфер заданного размера

Пример

<?php
const CHUNK_SIZE = 8192; // 8 KB
$in = fopen('huge.txt', 'r');
$out = fopen('huge_utf8.txt', 'w');
while (!feof($in)) {
    $chunk = fread($in, CHUNK_SIZE);
    $converted = mb_convert_encoding($chunk, 'UTF-8', 'Windows-1251');
    fwrite($out, $converted);
}
fclose($in); fclose($out);
echo 'Большой файл обработан порциями';
?>
Большой файл обработан порциями

Кодирование файла в PHP - comments

En
File php coded (php)