我从各种RSS订阅中阅读大量文本,并将它们插入到我的数据库中。

当然,在提要中使用了几种不同的字符编码,例如UTF-8和ISO 8859-1。

不幸的是,文本的编码有时会有问题。例子:

“Fußball”中的“ß”在我的数据库中应该是这样的:“Ÿ”。如果是“Ÿ”,则显示正确。 有时,“Fußball”中的“ß”在我的数据库中看起来像这样:“ß”。当然,这样就会显示错误。 在其他情况下,“ß”被保存为“ß”-因此没有任何变化。然后它也会被错误地显示。

我怎么做才能避免情况2和3?

我如何使所有的编码相同,最好是UTF-8?什么时候我必须使用utf8_encode(),什么时候我必须使用utf8_decode()(很清楚的效果是什么,但什么时候我必须使用函数?),什么时候我必须对输入什么都不做?

如何让所有编码都相同呢?也许使用函数mb_detect_encoding()?我能写一个函数吗?所以我的问题是:

如何找出文本使用的编码? 我如何将其转换为UTF-8 -无论旧的编码是什么?

这样的函数可行吗?

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

我已经测试过了,但是不行。有什么问题吗?


当前回答

您需要在输入上测试字符集,因为响应可以用不同的编码进行编码。

我强迫所有的内容被发送到UTF-8通过做检测和翻译使用以下功能:

function fixRequestCharset()
{
  $ref = array(&$_GET, &$_POST, &$_REQUEST);
  foreach ($ref as &$var)
  {
    foreach ($var as $key => $val)
    {
      $encoding = mb_detect_encoding($var[$key], mb_detect_order(), true);
      if (!$encoding)
        continue;
      if (strcasecmp($encoding, 'UTF-8') != 0)
      {
        $encoding = iconv($encoding, 'UTF-8', $var[$key]);
        if ($encoding === false)
          continue;
        $var[$key] = $encoding;
      }
    }
  }
}

该例程将把来自远程主机的所有PHP变量转换为UTF-8。

如果无法检测或转换编码,则忽略该值。

您可以根据自己的需要定制它。

只需在使用变量之前调用它。

其他回答

你的编码看起来像是用UTF-8编码了两次;也就是说,从其他编码,转换成UTF-8,再转换成UTF-8。就好像您有ISO 8859-1,从ISO 8859-1转换为UTF-8,并将新字符串处理为ISO 8859-1,以便再次转换为UTF-8。

下面是你所做的一些伪代码:

$inputstring = getFromUser();
$utf8string = iconv($current_encoding, 'utf-8', $inputstring);
$flawedstring = iconv($current_encoding, 'utf-8', $utf8string);

你应该试试:

使用mb_detect_encoding()或任何您喜欢使用的方法来检测编码 如果是UTF-8,转换成ISO 8859-1,然后重复步骤1 最后,转换回UTF-8

这是假设在“中间”转换中使用ISO 8859-1。如果您使用的是Windows-1252,则转换为Windows-1252 (latin1)。原始源编码并不重要;你在有缺陷的第二次转换中使用的是。

以下是我对所发生事情的猜测;要用四个字节代替一个扩展的ASCII字节,您几乎没有其他办法。

德语也使用ISO 8859-2和Windows-1250(拉丁语-2)。

我在http://deer.org.ua/2009/10/06/1/:上找到了一个解决方案

class Encoding
{
    /**
     * http://deer.org.ua/2009/10/06/1/
     * @param $string
     * @return null
     */
    public static function detect_encoding($string)
    {
        static $list = ['utf-8', 'windows-1251'];

        foreach ($list as $item) {
            try {
                $sample = iconv($item, $item, $string);
            } catch (\Exception $e) {
                continue;
            }
            if (md5($sample) == md5($string)) {
                return $item;
            }
        }
        return null;
    }
}

$content = file_get_contents($file['tmp_name']);
$encoding = Encoding::detect_encoding($content);
if ($encoding != 'utf-8') {
    $result = iconv($encoding, 'utf-8', $content);
} else {
    $result = $content;
}

我认为@是一个糟糕的决定,并对deer.org.ua的解决方案做了一些更改。

我知道这是一个老问题,但我认为一个有用的答案不会有坏处。我在桌面应用程序、SQLite和GET/POST变量之间的编码有问题。有些会使用UTF-8,有些会使用ASCII,当涉及到外国字符时,基本上所有事情都会搞砸。

这是我的解决方案。在处理之前,它会在每个页面加载时擦除GET/POST/REQUEST(我省略了cookie,但如果需要可以添加它们)。它在标题中工作得很好。如果PHP不能自动检测到源编码,它将抛出警告,因此这些警告将被@'s抑制。

//Convert everything in our vars to UTF-8 for playing nice with the database...
//Use some auto detection here to help us not double-encode...
//Suppress possible warnings with @'s for when encoding cannot be detected
try
{
    $process = array(&$_GET, &$_POST, &$_REQUEST);
    while (list($key, $val) = each($process)) {
        foreach ($val as $k => $v) {
            unset($process[$key][$k]);
            if (is_array($v)) {
                $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = $v;
                $process[] = &$process[$key][@mb_convert_encoding($k,'UTF-8','auto')];
            } else {
                $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = @mb_convert_encoding($v,'UTF-8','auto');
            }
        }
    }
    unset($process);
}
catch(Exception $ex){}

哈帕克斯的回答对我很管用。对我来说,这就足够了:

if (isUTF8($str)) {
    echo $str;
}
else
{
    echo iconv("ISO-8859-1", "UTF-8//TRANSLIT", $str);
}

mb_detect_encoding:

echo mb_detect_encoding($str, "auto");

Or

echo mb_detect_encoding($str, "UTF-8, ASCII, ISO-8859-1");

我真的不知道结果是什么,但我建议您只是使用不同编码的一些提要,并尝试mb_detect_encoding是否有效。

auto是“ASCII,JIS,UTF-8,EUC-JP,SJIS”的缩写。它返回检测到的字符集,您可以使用iconv将字符串转换为UTF-8。

<?php
function convertToUTF8($str) {
    $enc = mb_detect_encoding($str);

    if ($enc && $enc != 'UTF-8') {
        return iconv($enc, 'UTF-8', $str);
    } else {
        return $str;
    }
}
?>

我还没有测试过,所以不能保证。也许有更简单的方法。