Как бы вы создали строку из всех символов UTF-8? - PullRequest
5 голосов
/ 01 мая 2010

Существует множество способов представления +1 миллиона символов UTF-8 . Возьмите латинскую заглавную букву «А» с макроном (Ā). Это кодовая точка Unicode U+0100, шестнадцатеричное число 0xc4 0x80, десятичное число 196 128 и двоичный код 11000100 10000000.

Я хотел бы создать коллекцию первых 65 535 символов UTF-8 для использования в тестовых приложениях. Это все символы Unicode вплоть до кодовой точки U+FFFF (byte3).

Можно ли сделать что-то вроде цикла for($x=0), а затем преобразовать полученное десятичное число в другое основание (например, шестнадцатеричное), которое позволит создать соответствующий символ Юникода?

Я могу создать значение Ā, используя что-то вроде этого:

$char = "\xc4\x80";
// or
$char = chr(196).chr(128);

Однако я не уверен, как превратить это в автоматизированный процесс.

// fail!
$char = "\x". dechex($a). "\x". dexhex($b);

Ответы [ 5 ]

6 голосов
/ 01 мая 2010

Вы можете использовать iconv (или несколько других функций) для преобразования номера кодовой точки в строку UTF-8:

function unichr($i)
{
    return iconv('UCS-4LE', 'UTF-8', pack('V', $i));
}

$codeunits = array();
for ($i = 0; $i<0xD800; $i++)
    $codeunits[] = unichr($i);
for ($i = 0xE000; $i<0xFFFF; $i++)
    $codeunits[] = unichr($i);
$all = implode($codeunits);

(Я избежал суррогатного диапазона 0xD800–0xDFFF, поскольку они не имеют права самостоятельно вводить UTF-8; это будет «CESU-8».)

4 голосов
/ 01 мая 2010

Я не уверен, что вы можете сделать это программно, в основном потому, что есть разница между кодовой точкой Unicode и символом. См. http://www.unicode.org/standard/where для нескольких примеров символов, которые представлены комбинацией кодовых точек.

Некоторые кодовые точки сами по себе не имеют смысла и могут использоваться только в сочетании с другим символом (например, с ударением). См. http://www.unicode.org/charts/charindex.html для списка кодовых точек и посмотрите на раздел со всеми «комбинирующими» кодовыми точками.

Кроме того, для использования в тестировании приложений вам понадобится что-то еще, кроме списка возможных кодовых точек UTF-8, а именно несколько недействительных / искаженных последовательностей UTF-8, из которых ваше приложение должно иметь возможность корректно восстанавливаться. 1009 *

Для этого взгляните на стресс-тест Маркуса Куна в Юникоде .

1 голос
/ 01 мая 2010

Я быстро перевел это с C, но это должно дать вам идею:

function encodeUTF8( $inValue ) {
    $result = "";

    if ( $inValue < 0x00000080 ) {
        $result .= chr( $inValue );
        $extra = 0;
    } else if ( $inValue < 0x00000800 ) {
        $result .= chr( 0x00C0 | ( ( $inValue >> 6 ) & 0x001F ) );
        $extra = 6;
    } else if ( $inValue < 0x00010000 ) {
        $result .= chr( 0x00E0 | ( ( $inValue >> 12 ) & 0x000F ) );
        $extra = 12;
    } else if ( $inValue < 0x00200000 ) {
        $result .= chr( 0x00F0 | ( ( $inValue >> 18 ) & 0x0007 ) );
        $extra = 18;
    } else if ( $inValue < 0x04000000 ) {
        $result .= chr( 0x00F8 | ( ( $inValue >> 24 ) & 0x0003 ) );
        $extra = 24;
    } else if ( $inValue < 0x80000000 ) {
        $result .= chr( 0x00FC | ( ( $inValue >> 30 ) & 0x0001 ) );
        $extra = 30;
    }

    while ( $extra > 0 ) {
        $result .= chr( 0x0080 | ( ( $inValue >> ( $extra -= 6 ) ) & 0x003F ) );
    }

    return $result;
}

Логика логичная, но я не уверен насчет php, поэтому обязательно проверьте его. Я никогда не пытался использовать chr, как это.

Существует множество значений, которые вы не хотите кодировать, например 0xD000-0xDFFF, 0xE000-0xF8FF и 0xFFF0-0xFFFF, и есть несколько других пробелов для объединения символов и зарезервированных символов.

0 голосов
/ 04 марта 2017
<?php

function chr_utf8($n,$f='C*'){
return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n):
($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n):
($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):'')));
}

echo implode('',array_map('chr_utf8',range(0,65535)));

// Output a big string, you can increase the range to 1114111…
0 голосов
/ 01 мая 2010

:) конечно последний не сработает. \ x последовательность принадлежит строкам в двойных кавычках.

что не так с $char = chr(196).chr(128);? я имею в виду chr ($ a) .chr ($ b).

...