我收到的这个数据库中充满了法语的人名和数据,这意味着使用é,è,ö,û等字符。大约3000个条目。
显然,内部数据有时使用utf8_encode()编码,有时则不编码。这导致混乱的输出:在某些地方,角色显示正常,而在其他地方,他们没有。
起初我试图在UI中找到出现这些问题的每个地方,并在必要时使用utf8_decode(),但这实际上不是一个切实可行的解决方案。
我做了一些测试,没有理由首先使用utf8_encode,所以我宁愿删除所有这些,只是在UTF8中工作 - 在浏览器,中间件和数据库级别。所以我需要清理数据库,通过清理后的版本转换所有错误编码的数据。
问题:是否有可能在php中创建一个函数来检查utf8字符串是否正确编码(没有utf8_encode)或者没有(使用utf8_encode),如果是,则将其转换回原始状态?
换句话说:我想知道如何检测utf8内容已经utf8_encode()到utf8内容,而不是utf8_encode()d。
**更新:示例**
这是一个很好的例子:你带一个充满特殊字符的字符串并获取该字符串的副本和utf8_encode()它。我梦寐以求的函数接受两个字符串,第一个字符串保持不变,第二个字符串现在与字符串一相同。
我试过了:
$loc_fr = setlocale(LC_ALL, 'fr_BE.UTF8','fr_BE@euro', 'fr_BE', 'fr', 'fra', 'fr_FR');
$str1= "éèöûêïà ";
$str2 = utf8_encode($str1);
function convert_charset($str) {
$charset= mb_detect_encoding($str);
if( $charset=="UTF-8" ) {
return utf8_decode($str);
}
else {
return $str;
}
}
function correctString($str) {
echo "\nbefore: $str";
$str= convert_charset($str);
echo "\nafter: $str";
}
correctString($str1);
echo('<hr/>'."\n");
correctString($str2);
这让我:
before: éèöûêïà after: �������
before: éèöûêïà after: éèöûêïà
谢谢,
亚历
答案 0 :(得分:6)
从问题中你正在查看的字符编码镜头(这取决于文本编辑器的默认值,浏览器标题,数据库配置等)以及数据具有哪些字符编码转换,这一点并不完全清楚。经历了。例如,通过调整数据库配置,可能会纠正所有内容,这比对数据进行零碎的更改要好得多。
看起来这可能是utf8双重编码的问题,如果是这种情况,原始和损坏的数据都将在utf8中,因此编码检测不会为您提供所需的信息。在这种情况下的方法需要假设你的数据中哪些字符可以合理地出现:就PHP和Mysql而言,“é”是完全合法的utf8,所以你必须根据你对你的了解做出判断。数据及其作者必须被破坏。如果您只是技术人员,这些都是有风险的假设。幸运的是,如果您知道数据是法语的,并且只有3000条记录,那么可以做出这些假设。
下面是一个脚本,您可以首先调整以检查数据,然后进行更正,最后再次检查。它所做的只是将字符串处理为utf8,将其分解为字符,并将字符与预期的法语字符的白名单进行比较。如果字符串不在utf8中或包含法语中通常不期望的字符,则表示存在问题,例如:
PROBABLY OK Côte d'Azur
HAS NON-WHITELISTED CHAR Côte d'Azur 195,180 ô
NON-UTF8 C�e d'Azur
这是脚本,您需要从http://hsivonen.iki.fi/php-utf8/下载相关的unicode函数
<?php
// Download from http://hsivonen.iki.fi/php-utf8/
require "php-utf8/utf8.inc";
$my_french_whitelist = array_merge(
range(0,127), // throw in all the lower ASCII chars
array(
0xE8, // small e-grave
0xE9, // small e-acute
0xF4, // small o-circumflex
//... Will need to add other accented chars,
// Euro sign, and whatever other chars
// are normally expected in the data.
)
);
// NB, whether this string literal is in utf8
// depends on the encoding of the text editor
// used to write the code
$str1 = "Côte d'Azur";
$test_data = array(
$str1,
utf8_encode($str1),
utf8_decode($str1),
);
foreach($test_data as $str){
$questionable_chars = non_whitelisted(
$my_french_whitelist,
$str
);
if($questionable_chars===true){
p("NON-UTF8", $str);
}else if ($questionable_chars){
p(
"HAS NON-WHITELISTED CHAR",
$str,
implode(",", $questionable_chars),
unicodeToUtf8($questionable_chars)
);
}else{
p("PROBABLY OK", $str);
}
}
function non_whitelisted($whitelist, $utf8_str){
$codepoints = utf8ToUnicode($utf8_str);
if($codepoints===false){ // has non-utf8 char
return true;
}
return array_diff(
array_unique($codepoints),
$whitelist
);
}
function p(){
$args = func_get_args();
echo implode("\t", $args), "\n";
}
答案 1 :(得分:2)
我认为你可能会采取更多的编译方法。几个星期前我收到了一个在DB中动态编码的保加利亚数据库,但是当它移动到另一个数据库时,我得到了时髦的颜色???
我解决这个问题的方法是转储数据库,将数据库设置为utf8排序规则,然后将数据导入为二进制文件。这自动将所有内容转换为utf8并且不再给我了。
这是在MySQL
答案 2 :(得分:2)
连接数据库时,请记住始终使用mysql_set_charset('utf8',$ db_connection);
它将解决所有问题,它解决了我所有的问题。
请参阅:http://phpanswer.com/store-french-characters-into-mysql-db-and-display/
答案 3 :(得分:0)
正如您所说,您的数据有时会使用utf8_encode
转换,您的数据会使用UTF-8或ISO 8859-1进行编码(因为utf8_encode
会将ISO 8859-1转换为UTF-8 )。由于UTF-8将字符从128到255编码,其中两个字节以1100001x开头,因此您只需测试您的数据是否为有效的UTF-8,如果没有则进行转换。
如果数据已经是UTF-8(请参阅多个is_utf8
函数),请扫描所有数据;如果数据不是UTF-8,请使用utf8_encode
。
答案 4 :(得分:0)
我的问题是,不知何故,我在我的数据库中加入了像普通格式的à,é,ê或utf8编码的字符串。经过调查,我得出结论,一些浏览器(我不知道IE或FF或其他)正在编码提交的输入数据,因为没有故意添加utf8编码来处理提交表单。所以,如果我用utf8_encode读取数据,我将改变其他普通字符,反之亦然。
我的解决方案,在我研究上面给出的解决方案后: 1.我使用charset utf8创建了一个新数据库 2.导入数据库后我将sql dump文件中CREATE TABLE语句中的charset定义从Latin ....更改为UTF8。 3.从原始数据库导入数据 (直到这里可能只是为了更改现有数据库和表上的字符集,这只有在原始数据库不是utf8时) 4.使用简单格式替换utf8编码的字符,直接更新数据库中的内容,如
UPDATE `clients` SET `name` = REPLACE(`name`,"é",'é' ) WHERE `name` LIKE CONVERT( _latin1 '%é%' USING utf8 );
我把这个行放入db类(用于php代码)以确保它们是UTF8通信
$ this-&gt; query('SET CHARSET UTF8');
那么,请更新? (第4步) 我已经构建了一个带有可能编码的字符的数组
$special_chars = array(
'ù','û','ü',
'ÿ',
'à','â','ä','å','æ',
'ç',
'é','è','ê','ë',
'ï','î',
'ô','','ö','ó','ø',
'ü');
我用一对表格来建立一个数组,应该更新的字段
$where_to_look = array(
array("table_name" , "field_name"),
..... );
比,
foreach($special_chars as $char)
{
foreach($where_to_look as $pair)
{
//$table = $pair[0]; $field = $pair[1]
$sql = "SELECT id , `" . $pair[1] . "` FROM " .$pair[0] . " WHERE `" . $pair[1] . "` LIKE CONVERT( _latin1 '%" . $char . "%' USING utf8 );";
if($db->num_rows() > 0){
$sql1 = "UPDATE " . $pair[0] . " SET `" . $pair[1] . "` = REPLACE(`" . $pair[1] . "`,CONVERT( _latin1 '" . $char . "' USING utf8 ),'" . $char . "' ) WHERE `" . $pair[1] . "` LIKE CONVERT( _latin1 '%" . $char . "%' USING utf8 )";
$db1->query($sql1);
}
}
}
基本的ideea是使用mysql的编码功能来避免在mysql,apache,browser和back之间进行编码; 注意:我没有可用的php函数,如mb _....
最佳