pix*_*ine 6 php mysql character-encoding special-characters
我收到了这个充满法语人名和数据的数据库,这意味着使用é,è,ö,û等字符.大约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);
Run Code Online (Sandbox Code Playgroud)
这给了我:
before: éèöûêïà after: ???????
before: éèöûêïà after: éèöûêïà
Run Code Online (Sandbox Code Playgroud)
谢谢,
亚历克斯
小智 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
Run Code Online (Sandbox Code Playgroud)
这是脚本,你需要从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";
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10764 次 |
| 最近记录: |