Определите кодировку и сделайте все в UTF-8 - PullRequest
287 голосов
/ 26 мая 2009

Я читаю много текстов из различных RSS-каналов и вставляю их в свою базу данных.

Конечно, в каналах используется несколько различных кодировок символов, например, UTF-8 и ISO-8859-1.

К сожалению, иногда возникают проблемы с кодировкой текстов. Пример:

  1. «ß» в «Fußball» в моей базе данных должно выглядеть так: «ÂŸ». Если это «В», оно отображается правильно.

  2. Иногда «ß» в «Fußball» в моей базе данных выглядит так: «ÃƒÂŸ». Тогда это отображается неправильно, конечно.

  3. В других случаях «ß» сохраняется как «ß» - то есть без каких-либо изменений. Тогда это также отображается неправильно.

Что я могу сделать, чтобы избежать случаев 2 и 3?

Как я могу сделать все в той же кодировке, желательно UTF-8? Когда я должен использовать utf8_encode(), когда я должен использовать utf8_decode() (ясно, каков эффект, но когда я должен использовать функции?) И когда я ничего не должен делать с вводом?

Можете ли вы помочь мне и скажите, как сделать так, чтобы кодировка была одинаковой? Возможно с функцией mb_detect_encoding()? Могу ли я написать функцию для этого? Итак, мои проблемы:

  1. Как узнать, какую кодировку использует текст?
  2. Как преобразовать его в UTF-8 - какой бы ни была старая кодировка?

Будет ли такая функция работать?

function correct_encoding($text) {
    $current_encoding = mb_detect_encoding($text, 'auto');
    $text = iconv($current_encoding, 'UTF-8', $text);
    return $text;
}

Я проверял это, но это не работает. Что с ним не так?

Ответы [ 24 ]

0 голосов
/ 22 февраля 2012

Эта версия для немецкого языка, но вы можете изменить $ CHARSETS и $ TESTCHARS

class CharsetDetector
{
private static $CHARSETS = array(
"ISO_8859-1",
"ISO_8859-15",
"CP850"
);
private static $TESTCHARS = array(
"€",
"ä",
"Ä",
"ö",
"Ö",
"ü",
"Ü",
"ß"
);
public static function convert($string)
{
    return self::__iconv($string, self::getCharset($string));
}
public static function getCharset($string)
{
    $normalized = self::__normalize($string);
    if(!strlen($normalized))return "UTF-8";
    $best = "UTF-8";
    $charcountbest = 0;
    foreach (self::$CHARSETS as $charset) {
        $str = self::__iconv($normalized, $charset);
        $charcount = 0;
        $stop   = mb_strlen( $str, "UTF-8");

        for( $idx = 0; $idx < $stop; $idx++)
        {
            $char = mb_substr( $str, $idx, 1, "UTF-8");
            foreach (self::$TESTCHARS as $testchar) {

                if($char == $testchar)
                {

                    $charcount++;
                    break;
                }
            }
        }
        if($charcount>$charcountbest)
        {
            $charcountbest=$charcount;
            $best=$charset;
        }
        //echo $text."<br />";
    }
    return $best;
}
private static function __normalize($str)
{

$len = strlen($str);
$ret = "";
for($i = 0; $i < $len; $i++){
    $c = ord($str[$i]);
    if ($c > 128) {
        if (($c > 247)) $ret .=$str[$i];
        elseif ($c > 239) $bytes = 4;
        elseif ($c > 223) $bytes = 3;
        elseif ($c > 191) $bytes = 2;
        else $ret .=$str[$i];
        if (($i + $bytes) > $len) $ret .=$str[$i];
        $ret2=$str[$i];
        while ($bytes > 1) {
            $i++;
            $b = ord($str[$i]);
            if ($b < 128 || $b > 191) {$ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;}
            else $ret2.=$str[$i];
            $bytes--;
        }
    }
}
return $ret; 
}
private static function __iconv($string, $charset)
{
    return iconv ( $charset, "UTF-8" , $string );
}
}

0 голосов
/ 18 января 2012

После сортировки ваших php-скриптов, не забудьте сообщить mysql, какую кодировку вы передаете и хотели бы получить.

Пример: установить набор символов utf8

Передача данных utf8 в таблицу latin1 в сеансе ввода / вывода latin1 дает эти неприятные ошибки. Я вижу это через день в магазинах oscommerce. Назад и четвертый это может показаться правильным. Но phpmyadmin покажет правду. Сообщая mysql, какую кодировку вы передаете, она будет обрабатывать преобразование данных mysql для вас.

Как восстановить существующие зашифрованные данные MySQL - еще одна тема для обсуждения. :)

0 голосов
/ 22 июля 2017

Попробуйте без 'авто'

То есть:

mb_detect_encoding($text)

вместо:

mb_detect_encoding($text, 'auto')

Более подробную информацию можно найти здесь: mb_detect_encoding

0 голосов
/ 15 сентября 2011

Когда вы пытаетесь работать с несколькими языками, такими как японский и корейский, у вас могут возникнуть проблемы. mb_convert_encoding с параметром 'auto' работает не очень хорошо. Установка mb_detect_order ('ASCII, UTF-8, JIS, EUC-JP, SJIS, EUC-KR, UHC') не помогает, так как обнаружит EUC- * неправильно.

Я пришел к выводу, что, пока строки ввода исходят из HTML, он должен использовать 'charset' в метаэлементе. Я использую Simple HTML DOM Parser , потому что он поддерживает недопустимый HTML.

Приведенный ниже фрагмент извлекает элемент заголовка из веб-страницы. Если вы хотите преобразовать всю страницу, вы можете удалить несколько строк.

<?php
require_once 'simple_html_dom.php';

echo convert_title_to_utf8(file_get_contents($argv[1])), PHP_EOL;

function convert_title_to_utf8($contents)
{
    $dom = str_get_html($contents);
    $title = $dom->find('title', 0);
    if (empty($title)) {
        return null;
    }
    $title = $title->plaintext;
    $metas = $dom->find('meta');
    $charset = 'auto';
    foreach ($metas as $meta) {
        if (!empty($meta->charset)) { // html5
            $charset = $meta->charset;
        } else if (preg_match('@charset=(.+)@', $meta->content, $match)) {
            $charset = $match[1];
        }
    }
    if (!in_array(strtolower($charset), array_map('strtolower', mb_list_encodings()))) {
        $charset = 'auto';
    }
    return mb_convert_encoding($title, 'UTF-8', $charset);
}
...