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

Недавно пришлось перекодировать файлы сайта из 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" в текущей директории, и исправит в нем ошибки сериализации, если таковые имеются.
Код:
php 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 'Ура!!!';
Как бы ничего особенного, но поскольку регулярки пишутся редко, их "язык" быстро забывается, так что возможно кому-то пригодится.
Дата 2012-03-21 14:31:34

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

Вы не залогинены!

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