РазделыСтатьиРазработка сайтов → Перекодировка сайта с исправлением ошибок сериализации

Недавно пришлось перекодировать файлы сайта из cp-1251 в utf-8.
Ничего особенно сложного в этом нет, mb_convert_encoding в помощь.
Однако в файлах попадаются сериализованные массивы, и после перекодировки данные имеют другую длину, что приводит к ошибке при десериализации.

Для тех, кто не совсем "в курсе": в сериализованных файлах хранятся массивы (как правило это файлы конфигурации), которые нельзя или нежелательно хранить в обычных ini файлах.
Почему так происходит? Потому что в ini-файлах значения задаются с помощью двойных кавычек. И если внутри данных попадутся такие кавычки — труба, скрипт воспримет их как конец строки. Файл обработается неправильно, если обработается вообще. Вот такие данные и "сериализуют", чтобы задать четкую структуру массива данных, и тогда внутри можно писать любые символы, все будет обработано корректно.
Конкретно для этого файл принимает четкую структуру, в нем описываются теперь не только данные, но и их длина, что исключает ошибки и позволяет писать любые символы, зная что такая-то строчка содержит именно столько-то знаков. Короче, в таком случае ошибка интерпретации данных исключается.
Пример сериализованного массива:
Цитата:
a:3:{s:4:"link";a:4:{s:12:"slide100.jpg";s:30:"?module=fncatalogue&showitem=1";s:12:"slide500.jpg";s:30:"?module=fncatalogue&showitem=3";s:12:"slide200.jpg";s:30:"?module=fncatalogue&showitem=2";s:12:"slide400.jpg";s:30:"?module=fncatalogue&showitem=4";}s:7:"address";a:4:{s:12:"slide100.jpg";s:28:"Комсомольская 2";s:12:"slide500.jpg";s:15:"Кожара 59";s:12:"slide200.jpg";s:32:"Проспект Ленина 32";s:12:"slide400.jpg";s:38:"Старо-Черниговская 19";}s:11:"description";a:4:{s:12:"slide100.jpg";s:90:"Класс «Премиум» | 2 комнаты | евроремонт, Wi-Fi | от $ 30";s:12:"slide500.jpg";s:83:"Класс «Премиум» | 1 комната | евроремонт | от $ 25";s:12:"slide200.jpg";s:90:"Класс «Премиум» | 2 комнаты | евроремонт, Wi-Fi | от $ 28";s:12:"slide400.jpg";s:83:"Класс «Премиум» | 1 комната | евроремонт | от $ 21";}}
Как видно, в коде a: задает количество элементов массива, потом открываем скобки и перечисляем элементы. s:12: перед элементом означает что следующий за ним параметр содержит 12 символов.
При такой структуре можно "запоминать" массивы любой сложности и вложенности, и это замечательно. Но что случится если мы переконвертируем массив из однобайтной кодировки в UTF8?
Ничего хорошего, количество символов изменится если строка написана допустим кириллицей и не изменится, если эта строка на латинице.
В таком случае подобные файлы нужно переписывать заново, пересчитав цифры, следующие за s:

Вот код, который обработает файл "downloads.dat" в текущей директории, и исправит в нем ошибки сериализации, если таковые имеются.
Код:

mb_internal_encoding('utf-8');

    
$file 'downloads.dat';
    
$data file_get_contents($file);

    
//Раскомментируйте строчку ниже, если нужно ещё и переконвертировать:
    //$data = mb_convert_encoding($data, 'utf8', 'cp1251');

    //Исправление ошибок сериализации
    
$data preg_replace('#s:(\d+):"(.*?)";#se'"'s:'.strlen('$2').':\"$2\";'"$data );

    if (
file_put_contents($file$data) === false)
    echo 
'Не удалось сохранить файл: '.$file;
    else echo 
'Ура!!!';
Как бы ничего особенного, но поскольку регулярки пишутся редко, их "язык" быстро забывается, так что возможно кому-то пригодится.
21.03.2012 13:31 Автор/источник: admin

Комментировать

Вы не залогинены! Регистрация

Устал читать? Напиши! Или позвони +375 29 5344286. На связи по будним дням с 800 до 1700.