PHP - быстрый способ удалить все символы, не отображаемые в браузере, из строки utf8 - PullRequest
1 голос
/ 03 октября 2011

У меня есть небольшая грязная база данных, содержащая названия многих учреждений по всему миру.

Я хочу отображать их, включая национальные символы, но без недопустимых символов - те, которые отображаются в Firefox в виде номеров Unicode.

Как их отфильтровать?

База данных имеет кодировку utf8, но некоторые строки были вставлены с неправильными кодировками или в исходных кодах был беспорядок.

Я не хочу исправлять базу данных - она ​​слишком большая. Я хочу просто отфильтровать это - "с глаз долой"

Ответы [ 3 ]

6 голосов
/ 03 октября 2011

Я хочу просто отфильтровать его

У вас есть неопределенная кодировка / кодировка с вашими данными.Это огромная проблема.

Сначала вы можете попробовать , чтобы преобразовать его в utf-8, а затем убрать все непечатаемые символы:

$str = iconv('utf-8', 'utf-8//ignore', $str);

echo preg_replace('/[^\pL\pN\pP\pS\pZ]/u', '', $str);

Проблема, что функция iconv может только попробовать.Это отбросит любую недопустимую последовательность символов.Начиная с php 5.4, он будет отбрасывать полную строку, если указанная кодировка ввода недопустима.

Вы увидите предупреждение, начиная с PHP 5.3, что входная строка имеет недопустимую кодировку.Вы можете обойти это, удалив все недействительные utf-8 последовательности байтов first:

$str = valid_utf8_bytes($str);

echo preg_replace('/[^\pL\pN\pP\pS\pZ]/u', '', $str);

/**
 * get valid utf-8 byte squences
 *
 * take over all matching bytes, drop an invalid sequence until first
 * non-matching byte.
 * 
 * @param string $str
 * @return string
 */
function valid_utf8_bytes($str)
{
    $return = '';
    $length = strlen($str);
    $invalid = array_flip(array("\xEF\xBF\xBF" /* U-FFFF */, "\xEF\xBF\xBE" /* U-FFFE */));

    for ($i=0; $i < $length; $i++)
    {
        $c = ord($str[$o=$i]);

        if ($c < 0x80) $n=0; # 0bbbbbbb
        elseif (($c & 0xE0) === 0xC0) $n=1; # 110bbbbb
        elseif (($c & 0xF0) === 0xE0) $n=2; # 1110bbbb
        elseif (($c & 0xF8) === 0xF0) $n=3; # 11110bbb
        elseif (($c & 0xFC) === 0xF8) $n=4; # 111110bb
        else continue; # Does not match

        for ($j=++$n; --$j;) # n bytes matching 10bbbbbb follow ?
            if ((++$i === $length) || ((ord($str[$i]) & 0xC0) != 0x80))
                continue 2
        ;

        $match = substr($str, $o, $n);

        if ($n === 3 && isset($invalid[$match])) # test invalid sequences
            continue;

        $return .= $match;
    }
    return $return;
}
1 голос
/ 03 октября 2011

С базой данных проблема может быть не совсем - если таблицы имеют кодировку utf8, строки в них должны быть преобразованы (я думаю).Проблема, с которой я столкнулся, заключалась в правильном обеспечении согласованности кодировки.Например, соединитель mysqli, по умолчанию, возвращается к Latin-8859 IIRC, так что вполне возможно иметь вывод в utf8, базу данных в utf8 и все же в конечном итоге получить?символы, потому что они преобразованы в латиницу с помощью коннектора mysqli.

Для обеспечения utf8 по всем направлениям вам нужно сделать что-то вроде:

В базе данных:

убедитесь, что параметры сортировки похожи на utf8_general_ci

В верхней части файла представления PHP:

<?php header('Content-Type:Text/Plain;charset=utf-8'); ?>

В мета-HTMLтег (необязательно):

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

И в соединителе базы данных (на примере MySQLi):

mysqli::set_charset('utf8'); #note that for MySQL it isn't hyphenated

Вы можете обнаружить, что решаетпроблема в любом случае.

0 голосов
/ 03 октября 2011

Если проблема связана с базой данных, которая, по-видимому, возникает в вашем случае (и устранить ее невозможно), то, возможно, просто распечатайте каждый символ из строки, используя ORD, и найдите значение для управляющего символа, которое не является хорошо отправлено.

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

...