Как выполнить перекодировку файлов в 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 'Большой файл обработан порциями';
?>
Большой файл обработан порциями