我从各种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。
如果无法检测或转换编码,则忽略该值。
您可以根据自己的需要定制它。
只需在使用变量之前调用它。
我一直在寻找编码的解决方案,这个页面可能是多年搜索的结论!我测试了你提到的一些建议,以下是我的笔记:
这是我的测试字符串:
这是一个“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作为参数。
但是,我只是在插入之前重新编码,所以对我来说这不是问题。
对于汉字,通常采用GBK编码。此外,在测试时,投票最多的答案不成立。这里有一个简单的修复方法,让它也能正常工作:
function toUTF8($raw) {
try{
return mb_convert_encoding($raw, "UTF-8", "auto");
}catch(\Exception $e){
return mb_convert_encoding($raw, "UTF-8", "GBK");
}
}
注:这个解决方案是在2017年编写的,应该可以修复当时PHP的问题。我还没有测试最新的PHP是否已经正确理解自动。
检测编码是困难的。
mb_detect_encoding works by guessing, based on a number of candidates that you pass it. In some encodings, certain byte-sequences are invalid, an therefore it can distinguish between various candidates. Unfortunately, there are a lot of encodings, where the same bytes are valid (but different). In these cases, there is no way to determine the encoding; You can implement your own logic to make guesses in these cases. For example, data coming from a Japanese site might be more likely to have a Japanese encoding.
As long as you only deal with Western European languages, the three major encodings to consider are utf-8, iso-8859-1 and cp-1252. Since these are defaults for many platforms, they are also the most likely to be reported wrongly about. Eg. if people use different encodings, they are likely to be frank about it, since else their software would break very often. Therefore, a good strategy is to trust the provider, unless the encoding is reported as one of those three. You should still doublecheck that it is indeed valid, using mb_check_encoding (note that valid is not the same as being - the same input may be valid for many encodings). If it is one of those, you can then use mb_detect_encoding to distinguish between them. Luckily that is fairly deterministic; You just need to use the proper detect-sequence, which is UTF-8,ISO-8859-1,WINDOWS-1252.
一旦检测到编码,就需要将其转换为内部表示(UTF-8是唯一明智的选择)。函数utf8_encode将ISO-8859-1转换为UTF-8,因此它只能用于特定的输入类型。对于其他编码,使用mb_convert_encoding。