2016-10-19 3 views
0

Мне нужна функция, которая будет правильно преобразовывать символы, отличные от ASCII, в представление \ uXXXX. Я знаю, что json_encode делает это, но он добавляет двойные кавычки к строке, и я предполагаю, что может быть более совершенное решение, потребляющее меньше процессора, чем в случае использования json_encode для каждого символа.Преобразование символов Юникода в uXXXX, не используя json_encode

Вот текущее решение:

$input=preg_replace_callback('#([^\r\n\t\x20-\x7f])#u', function($m) { 
     return trim(json_encode($m[1]),'"'); 
    }, $input); 

Кто-нибудь есть идея быстрого и легкое решение?

ответ

2

Поскольку ваше текущее решение использует модификатор regex u, я предполагаю, что ваш вход кодируется как UTF-8.

Следующее решение, безусловно, не проще (кроме регулярного выражения), и я даже не уверен, что он быстрее, но он более низкоуровневый и показывает фактическую процедуру экранирования.

$input = preg_replace_callback('#[^\x00-\x7f]#u', function($m) { 
    $utf16 = mb_convert_encoding($m[0], 'UTF-16BE', 'UTF-8'); 
    if (strlen($utf16) <= 2) { 
     $esc = '\u' . bin2hex($utf16); 
    } 
    else { 
     $esc = '\u' . bin2hex(substr($utf16, 0, 2)) . 
       '\u' . bin2hex(substr($utf16, 2, 2)); 
    } 
    return $esc; 
}, $input); 

Одной из основных проблем является то, что PHP не имеет ord function that works with UTF-8. Вы либо должны использовать mb_convert_encoding, либо вам нужно свернуть собственный декодер UTF-8 (см. Связанный вопрос), что позволит обеспечить дополнительные оптимизации. Двух- и трехбайтовые последовательности UTF-8 отображаются в единый кодовый блок UTF-16. Для четырехбайтовых последовательностей требуется два блока кода (высокий и низкий суррогат).

Если вы нацелены на простоту и удобочитаемость, вы, вероятно, не сможете обойти подход json_encode.

+0

Спасибо за объяснение. Давайте сохраним ваш ответ как хороший вариант. Может быть, кто-то проверит оба варианта скорости :). – NikitOn

Смежные вопросы