Оптимизация функции конвертации строки из charcode в UTF-8

igrok54

Ищущий
Используется при парсинге базы товаров из XLS-файла
Была такая функция:
Код:
function uc2html($str) {
   $ret = '';
   for( $i=0; $i<strlen($str)/2; $i++ ) {
     $charcode = ord($str[$i*2])+256*ord($str[$i*2+1]);
     $ret .= html_entity_decode('&#'.$charcode.';',ENT_NOQUOTES,'UTF-8');
   }
   return $ret;
}
Excel-файл размером 1.5Мб разбирался секунд 40-45, и наибольшие тормоза создает именно данная функция.

Перенос в функции html_entity_decode из цикла в результирующую строку сократил время обработки файла в 3 раза - время обработки стало около 15 секунд.
Код:
function uc2html($str) {
    $ret = '';
    for( $i=0; $i<strlen($str)/2; $i++ ) {
        $charcode = ord($str[$i*2])+256*ord($str[$i*2+1]);
        $ret .= '&#'.$charcode.';';
    }
    return html_entity_decode($ret,ENT_NOQUOTES,'UTF-8');
}
Вопрос: можно ли еще оптимизировать эту функцию? Хотелось бы избавиться от цикла. Мысли такие: заменить цикл на str_split -> array_map -> implode -> html_entity_decode
Но запутался в математике. Прошу помочь.
 

igrok54

Ищущий
iconv('ucs-2','utf-8',$str) выдает совершенно китайские иероглифы на выходе.
 

fixxxer

К.О.
Партнер клуба
Значит не угадал с кодировкой. Пробуй UCS-2BE UCS-2LE итд. Ну раз это ексель, думаю, что там LE :)
 

igrok54

Ищущий
Архив с ридером, упрощенный вариант - скормил в форму XLS - получил массив данных первого листа .Первый ряд в xls-файле становится ключами в массиве для ячеек последующих рядов.
 
Последнее редактирование:

igrok54

Ищущий
Нужно ли рассказывать про phpExcel?
Не нужно. Но использовать библиотеку, которая весит в три раза больше движка сайта как-то не то... Тем более, что данный класс хоть и старенький, но работает на раз-два. Само распарсивание xls происходит практически мгновенно и корректно. Моя проблема уже на стадии обработки полученных данных.
 

WMix

герр M:)ller
Партнер клуба
for( $i=0; $i<strlen($str)/2; $i+=2 )
$str[$i] << не умножать!
и будет ракета!
 

ksnk

прохожий
@WMix, если не умножать, то и в условии не надо делить на 2 ;)

Кстати, тестовый xls, состряпанный моим MSExcel 2007, сохраненный как `xls 2003` из таблички 3x2 завесил машину. Так и должно быть?
 

igrok54

Ищущий
@fixxxer, Огромное спасибо за подсказки!
Вопрос решил кодом, обрабатывающим всю строку разом:
Код:
mb_convert_encoding($str,'UTF-8','UCS-2LE');
Вместо UCS-2LE можно UTF-16LE и byte2le - любая из трех раскодирует без потерь. Интересно, почему?
Время выполнения скрипта стало (Ура!) 0.2 сек. Прогресс 45сек -> 15сек -> 0.2сек.
 

fixxxer

К.О.
Партнер клуба
Ну это все 16-битный little-endian юникод, отличаются поддержкой суррогатных пар, поддержкой всяких там китайских иероглифов не из basic multilingual набора итд, не думаю, что это для твоей задачи имеет значение. А какой из них что умеет/не умеет - я уже сам давно запутался :)
 
Сверху