我从各种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;
}

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


当前回答

我一直在寻找编码的解决方案,这个页面可能是多年搜索的结论!我测试了你提到的一些建议,以下是我的笔记:

这是我的测试字符串:

这是一个“wròng wrìtten”字符串bùt I nèed到pù‘sòme’的特殊 Chàrs看thèm, convertèd看fùnctìon!!&就是这样!

我执行INSERT操作将该字符串保存在数据库中的字段中,该字段设置为utf8_general_ci

我的页面的字符集是UTF-8。

如果我像这样做一个INSERT,在我的数据库中,我有一些字符可能来自火星…

所以我需要把它们转换成一些“理智的”UTF-8。我尝试utf8_encode(),但仍然外星人字符入侵我的数据库…

所以我尝试使用函数forceeutf8张贴在数字8,但在数据库中保存的字符串看起来像这样:

这是一个“wròng wrà tten”的字符串bùt I nèed to pù'sòme'特殊 Chà rs看thèm, convertèd由fùnctà on!!&就是这样!

所以在这个页面上收集更多的信息,并将它们与其他页面上的其他信息合并,我用这个解决方案解决了我的问题:

$finallyIDidIt = mb_convert_encoding(
  $string,
  mysql_client_encoding($resourceID),
  mb_detect_encoding($string)
);

现在在我的数据库中,我有了编码正确的字符串。

注意:

唯一需要注意的是mysql_client_encoding函数! 您需要连接到数据库,因为这个函数需要一个资源ID作为参数。

但是,我只是在插入之前重新编码,所以对我来说这不是问题。

其他回答

一个实现isutf8函数的好方法可以在php.net上找到:

function isUTF8($string) {
    return (utf8_encode(utf8_decode($string)) == $string);
}

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;
    }
}
?>

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

关于mb_detect_encoding和mb_convert_encoding有趣的事情是,您建议的编码顺序确实很重要:

// $input is actually UTF-8

mb_detect_encoding($input, "UTF-8", "ISO-8859-9, UTF-8");
// ISO-8859-9 (WRONG!)

mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9");
// UTF-8 (OK)

因此,在指定预期的编码时,您可能希望使用特定的顺序。不过,请记住,这并非万无一失。

如果您将utf8_encode()应用于一个已经UTF-8的字符串,它将返回乱码的UTF-8输出。

我做了一个函数来解决所有这些问题。它被称为Encoding::toUTF8()。

你不需要知道字符串的编码是什么。它可以是Latin1 (ISO 8859-1)、Windows-1252或UTF-8,或者字符串可以是它们的混合。Encoding::toUTF8()将所有内容转换为UTF-8。

我这样做是因为一个服务给了我一个混乱的数据提要,在同一个字符串中混合了UTF-8和Latin1。

用法:

require_once('Encoding.php');
use \ForceUTF8\Encoding;  // It's namespaced now.

$utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);

$latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

下载:

https://github.com/neitanod/forceutf8

我还包含了另一个函数Encoding::fixUFT8(),它将修复每个看起来乱码的UTF-8字符串。

用法:

require_once('Encoding.php');
use \ForceUTF8\Encoding;  // It's namespaced now.

$utf8_string = Encoding::fixUTF8($garbled_utf8_string);

例子:

echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");

将输出:

Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football

我在一个名为Encoding的类上将函数(forceeutf8)转换为一系列静态函数。新函数是Encoding::toUTF8()。

我在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的解决方案做了一些更改。