PHP Conference Japan 2024

utf8_decode

(PHP 4, PHP 5, PHP 7, PHP 8)

utf8_decode 将字符串从 UTF-8 转换为 ISO-8859-1,替换无效或无法表示的字符

警告

此函数自 PHP 8.2.0 起已弃用。强烈建议不要依赖此函数。

描述

#[\Deprecated]
utf8_decode(string $string): string

此函数将字符串 stringUTF-8 编码转换为 ISO-8859-1。字符串中不是有效 UTF-8 的字节,以及 UTF-8 字符集中不存在于 ISO-8859-1 中的字符(即,代码点高于 U+00FF),将被替换为 ?

注意:

许多标记为使用 ISO-8859-1 字符编码的网页实际上使用类似的 Windows-1252 编码,并且 Web 浏览器会将 ISO-8859-1 网页解释为 Windows-1252Windows-1252 提供了额外的可打印字符,例如欧元符号 () 和弯引号 ( ),而不是某些 ISO-8859-1 控制字符。此函数不会正确转换此类 Windows-1252 字符。如果需要 Windows-1252 转换,请使用其他函数。

参数

string

一个 UTF-8 编码的字符串。

返回值

返回 string 的 ISO-8859-1 转换结果。

变更日志

版本 描述
8.2.0 此函数已被弃用。
7.2.0 此函数已从 XML 扩展移至 PHP 的核心。在以前的版本中,只有在安装了 XML 扩展时才能使用它。

示例

示例 #1 基本示例

<?php
// 将字符串 'Zoë' 从 UTF-8 转换为 ISO 8859-1
$utf8_string = "\x5A\x6F\xC3\xAB";
$iso8859_1_string = utf8_decode($utf8_string);
echo
bin2hex($iso8859_1_string), "\n";

// 无效的 UTF-8 序列将被替换为 '?'
$invalid_utf8_string = "\xC3";
$iso8859_1_string = utf8_decode($invalid_utf8_string);
var_dump($iso8859_1_string);

// ISO 8859-1 中不存在的字符,例如
// '€'(欧元符号)也会被替换为 '?'
$utf8_string = "\xE2\x82\xAC";
$iso8859_1_string = utf8_decode($utf8_string);
var_dump($iso8859_1_string);
?>

以上示例将输出

5a6feb
string(1) "?"
string(1) "?"

注释

注意: 弃用和替代方案

此函数自 PHP 8.2.0 起已弃用,将在未来版本中移除。应检查现有用法并替换为适当的替代方案。

可以使用 mb_convert_encoding() 实现类似的功能,该函数支持 ISO-8859-1 和许多其他字符编码。

<?php
$utf8_string
= "\xC3\xAB"; // 'ë'(带分音符的 e)在 UTF-8 中
$iso8859_1_string = mb_convert_encoding($utf8_string, 'ISO-8859-1', 'UTF-8');
echo
bin2hex($iso8859_1_string), "\n";

$utf8_string = "\xCE\xBB"; // 'λ'(希腊小写 lambda)在 UTF-8 中
$iso8859_7_string = mb_convert_encoding($utf8_string, 'ISO-8859-7', 'UTF-8');
echo
bin2hex($iso8859_7_string), "\n";

$utf8_string = "\xE2\x82\xAC"; // '€'(欧元符号)在 UTF-8 中(在 ISO-8859-1 中不存在)
$windows_1252_string = mb_convert_encoding($utf8_string, 'Windows-1252', 'UTF-8');
echo
bin2hex($windows_1252_string), "\n";
?>

以上示例将输出

eb
eb
80

其他可能可用的选项(取决于安装的扩展)是 UConverter::transcode()iconv()

以下所有操作都产生相同的结果

<?php
$utf8_string
= "\x5A\x6F\xC3\xAB"; // 'Zoë' 使用 UTF-8 编码
$iso8859_1_string = utf8_decode($utf8_string);
echo
bin2hex($iso8859_1_string), "\n";

$iso8859_1_string = mb_convert_encoding($utf8_string, 'ISO-8859-1', 'UTF-8');
echo
bin2hex($iso8859_1_string), "\n";

$iso8859_1_string = iconv('UTF-8', 'ISO-8859-1', $utf8_string);
echo
bin2hex($iso8859_1_string), "\n";

$iso8859_1_string = UConverter::transcode($utf8_string, 'ISO-8859-1', 'UTF8');
echo
bin2hex($iso8859_1_string), "\n";
?>

以上示例将输出

5a6feb
5a6feb
5a6feb
5a6feb
'?' 指定为 UConverter::transcode()'to_subst' 选项,对于无效或无法用 ISO 8859-1 表示的字符串,会得到与 utf8_decode() 相同的结果。
<?php
$utf8_string
= "\xE2\x82\xAC"; // € (欧元符号) 在 ISO 8859-1 中不存在
$iso8859_1_string = UConverter::transcode(
$utf8_string, 'ISO-8859-1', 'UTF-8', ['to_subst' => '?']
);
var_dump($iso8859_1_string);
?>

以上示例将输出

sring(1) "?"

参见

添加注释

用户贡献的注释 32 条注释

info at vanylla dot it
15 年前
重要提示:转换包含欧元符号的 UTF8 数据时,请勿使用 utf_decode 函数。

utf_decode 将数据转换为 ISO-8859-1 字符集。但是 ISO-8859-1 字符集不包含欧元符号,因此欧元符号将转换为问号字符“?”。

为了正确转换包含欧元符号的 UTF8 数据,您必须使用

iconv("UTF-8", "CP1252", $data)
alexlevin at kvadro dot net
17 年前
如果您运行 Gentoo Linux 并遇到某些 PHP4 应用程序出现以下问题
Call to undefined function: utf8_decode()
尝试使用启用了“expat”标志重新合并 PHP4。
deceze at gmail dot com
13 年前
请注意,utf8_decode 只是将 UTF-8 编码的字符串转换为 ISO-8859-1。更合适的名称应该是 utf8_to_iso88591。如果您的文本已使用 ISO-8859-1 编码,则不需要此函数。如果您不想使用 ISO-8859-1,则不需要此函数。

请注意,UTF-8 可以表示比 ISO-8859-1 多得多的字符。尝试将包含无法用 ISO-8859-1 表示的字符的 UTF-8 字符串转换为 ISO-8859-1 将使您的文本混乱和/或导致字符丢失。尝试使用此函数转换未以 UTF-8 编码的文本很可能会使文本混乱。

如果您需要将任何文本从任何编码转换为任何其他编码,请改用 iconv()。
gabriel arobase gabsoftware dot com
13 年前
如果您想从数据库中检索一些 UTF-8 数据,则不需要 utf8_decode()。

只需在任何 SELECT 之前执行以下查询

$result = mysql_query("SET NAMES utf8");
lukasz dot mlodzik at gmail dot com
16 年前
更新为 MARC13 函数 utf2iso()
我正在使用它来处理 AJAX POST 调用。
尽管使用了
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'; charset='utf-8');
它仍然使用 UTF-16 编码波兰语字母

这只适用于波兰语字母



<?php
function utf16_2_utf8 ($nowytekst) {
$nowytekst = str_replace('%u0104','Ą',$nowytekst); //Ą
$nowytekst = str_replace('%u0106','Ć',$nowytekst); //Ć
$nowytekst = str_replace('%u0118','Ę',$nowytekst); //Ę
$nowytekst = str_replace('%u0141','Ł',$nowytekst); //Ł
$nowytekst = str_replace('%u0143','Ń',$nowytekst); //Ń
$nowytekst = str_replace('%u00D3','Ó',$nowytekst); //Ó
$nowytekst = str_replace('%u015A','Ś',$nowytekst); //Ś
$nowytekst = str_replace('%u0179','Ź',$nowytekst); //Ź
$nowytekst = str_replace('%u017B','Ż',$nowytekst); //Ż

$nowytekst = str_replace('%u0105','ą',$nowytekst); //ą
$nowytekst = str_replace('%u0107','ć',$nowytekst); //ć
$nowytekst = str_replace('%u0119','ę',$nowytekst); //ę
$nowytekst = str_replace('%u0142','ł',$nowytekst); //ł
$nowytekst = str_replace('%u0144','ń',$nowytekst); //ń
$nowytekst = str_replace('%u00F3','ó',$nowytekst); //ó
$nowytekst = str_replace('%u015B','ś',$nowytekst); //ś
$nowytekst = str_replace('%u017A','ź',$nowytekst); //ź
$nowytekst = str_replace('%u017C','ż',$nowytekst); //ż
return ($nowytekst);
}
?>

一切都很顺利,但它没有更改“%u00D3”、“Ó”和“%u00F3”、“ó”。我不知道该怎么处理。

记住!文件必须以 UTF-8 编码保存。
亚历山大
7年前
除了 yannikh 在 gmeil dot com 上的注释外,另一种方法是从类似 unix 控制台的字符串中解码非拉丁字符

C=RU, L=\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0,

<?php preg_replace_callback('/\\\\x([0-9A-F]{2})/', function($a){ return pack('H*', $a[1]); }, $str); ?>

上面的代码将输出
C=RU, L=莫斯科,
山姆
17 年前
除了 yannikh 的注释外,要转换十六进制 utf8 字符串

<?php

echo utf8_decode("\x61\xc3\xb6\x61");
// 按预期工作

$abc="61c3b661";
$newstr = "";
$l = strlen($abc);
for (
$i=0;$i<$l;$i+=2){
$newstr .= "\x".$abc[$i].$abc[$i+1];
}
echo
utf8_decode($newstr);
// 或各种“\x”:“\\x”等不会输出您想要的内容

echo utf8_decode(pack('H*',$abc));
// 这会输出正确的字符串,就像第一行一样。

?>
Aidan Kehoe <php-manual at parhasard dot net>
20年前
我发现检查某些内容是否为有效 UTF-8 的最快方法是
<?php
if (iconv('UTF-8', 'UTF-8', $input) != $input) {
/* 它不是 UTF-8——对我来说,它可能是 CP1252,Windows
拉丁语 1 版本,带有定向引号
和欧元符号。 */
}
?>.
如果告诉 iconv() C 库一个字符串是 UTF-8 而它不是,则该库将失败;PHP 库不会失败,它只是返回转换到失败点,因此您必须将结果与输入进行比较以找出转换是否成功。
j dot dittmer at portrix dot net
19年前
上一条评论中的正则表达式有一些错别字。这是一个
语法上有效的,不知道是否正确。
您必须将表达式连接在一长行中。

^(
[\x00-\x7f]|
[\xc2-\xdf][\x80-\xbf]|
[\xe0][\xa0-\xbf][\x80-\xbf]|
[\xe1-\xec][\x80-\xbf]{2}|
[\xed][\x80-\x9f][\x80-\xbf]|
[\xee-\xef][\x80-\xbf]{2}|
[\xf0][\x90-\xbf][\x80-\xbf]{2}|
[\xf1-\xf3][\x80-\xbf]{3}|
[\xf4][\x80-\x8f][\x80-\xbf]{2}
)*$
克里斯托弗
12年前
在数组上使用它的首选方法是使用内置的 PHP 函数“array_map()”,例如
$array = array_map("utf8_decode", $array);
thierry.bo # netcourrier point com
19年前
为了回应 fhoech(2005年9月22日11:55),我刚刚使用您的正则表达式、'j dot dittmer'(2005年9月20日06:30)正则表达式(消息#56962)、`php-note-2005`(2005年2月17日08:57)在其关于`mb-detect-encoding`页面的消息中的正则表达式(http://us3.php.net/manual/en/function.mb-detect-encoding.php#50087),他使用的是来自 W3C 的正则表达式(http://w3.org/International/questions/qa-forms-utf-8.html),以及 PHP mb_detect_encoding 函数对文件 UTF-8-test.txt 进行了同步测试。

以下是结果摘要

使用 phpnote 正则表达式,有 201 行是有效的 UTF8 字符串
使用 j.dittmer 正则表达式,有 203 行是有效的 UTF8 字符串
使用 fhoech 正则表达式,有 200 行是有效的 UTF8 字符串
使用 mb_detect_encoding,有 239 行是有效的 UTF8 字符串

以下是差异行(从左到右,phpnote、j.dittmer 和 fhoech)

第 70 行:不是 UTF8|是 UTF8!|是 UTF8!:2.1.1 1 字节(U-00000000):""
第 79 行:不是 UTF8|是 UTF8!|是 UTF8!:2.2.1 1 字节(U-0000007F):" "
第 81 行:是 UTF8!|是 UTF8!|不是 UTF8:2.2.3 3 字节(U-0000FFFF):"&#65535;" |
第 267 行:是 UTF8!|是 UTF8!|不是 UTF8:5.3.1 U+FFFE = ef bf be = "&#65534;" |
第 268 行:是 UTF8!|是 UTF8!|不是 UTF8:5.3.2 U+FFFF = ef bf bf = "&#65535;" |

有趣的是,您说您的正则表达式修正了在 5.3 部分失败的 j.dittmer 正则表达式,但在我的测试中,我得到了相反的结果?!

我在 Windows XP 上使用 PHP 4.3.11dev 运行了此测试。也许这些差异来自操作系统或 PHP 版本。

对于 mb_detect_encoding,我使用了以下命令

mb_detect_encoding($line, 'UTF-8, ISO-8859-1, ASCII');

[email protected]
1年前
$string = "Bjørn Johansen";

echo mb_convert_encoding($string, 'ISO-8859-1', 'UTF-8');

----
输出: "Bjørn Johansen"
[email protected]
9年前
// 这最终帮助我完成了工作,感谢Blackbit,不得不修改已弃用的ereg
// 原始注释:“Squirrelmail在源代码中包含一个将Unicode转换为实体的不错函数:”

function charset_decode_utf_8 ($string) {
/* 只有在存在8位字符时才执行缓慢的转换 */
/* 避免在ereg范围内使用0xA0 (\240)。RH73不喜欢那样 */
if (!preg_match("/[\200-\237]/", $string)
&& !preg_match("/[\241-\377]/", $string)
) {
return $string;
}

// 解码三字节Unicode字符
$string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e",
"'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'",
$string
);

// 解码两字节Unicode字符
$string = preg_replace("/([\300-\337])([\200-\277])/e",
"'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'",
$string
);

return $string;
}
[email protected]
10年前
使用utf8_decode对我来说还不够,因为我从另一个网站获取页面内容。问题出现在不同于标准拉丁语的字母表中。例如,一些字符(对应于HTML代码&bdquo;,&nbsp;等)被转换为“?”或“xA0”(十六进制值)。您需要在执行utf8_decode之前进行一些转换。并且您不能简单地替换,因为它们可能是字符的2字节代码的一部分(UTF-8使用2字节)。接下来是针对西里尔字母表的,但对于其他字母表来说也应该非常接近。

function convertMethod($text){
//问题在于utf8_decode将HTML字符&bdquo;等转换为?或&nbsp;转换为\xA0。并且您不能替换它们,因为它们位于某些字符字节中,并且您破坏了西里尔(或其他字母表)字符。
$problem_enc=array(
'euro',
'sbquo',
'bdquo',
'hellip',
'dagger',
'Dagger',
'permil',
'lsaquo',
'lsquo',
'rsquo',
'ldquo',
'rdquo',
'bull',
'ndash',
'mdash',
'trade',
'rsquo',
'brvbar',
'copy',
'laquo',
'reg',
'plusmn',
'micro',
'para',
'middot',
'raquo',
'nbsp'
);
$text=mb_convert_encoding($text,'HTML-ENTITIES','UTF-8');
$text=preg_replace('#(?<!\&ETH;)\&('.implode('|',$problem_enc).');#s','--amp{$1}',$text);
$text=mb_convert_encoding($text,'UTF-8','HTML-ENTITIES');
$text=utf8_decode($text);
$text=mb_convert_encoding($text,'HTML-ENTITIES','UTF-8');
$text=preg_replace('#\-\-amp\{([^\}]+)\}#su','&$1;',$text);
$text=mb_convert_encoding($text,'UTF-8','HTML-ENTITIES');
return $text;
}

如果这不起作用,请尝试在某些地方设置“die($text);”以查看此行发生了什么。最好使用长文本进行测试。很有可能破坏其他字母字符。在这种情况下,很可能对于您的字母表设置“&ETH;”是不正确的。您需要在此preg_replace之后设置“die($text);”并查看设置“--amp”之前字符的HTML代码。
[email protected]
16 年前
哎!错误不在函数'utf8_decode'中。错误在函数'mb_detect_encoding'中。如果您在末尾添加一个特殊字符的单词,例如'accentué',这将导致错误的结果(UTF-8),但如果您在末尾添加另一个字符,例如'accentuée',您将获得正确的结果。因此,您应该始终在此检查中向字符串添加ISO-8859-1字符。我的建议是使用空格。
我试过了,它有效!

function ISO_convert($array)
{
$array_temp = array();

foreach($array as $name => $value)
{
if(is_array($value))
$array_temp[(mb_detect_encoding($name." ",'UTF-8,ISO-8859-1') == 'UTF-8' ? utf8_decode($name) : $name )] = ISO_convert($value);
else
$array_temp[(mb_detect_encoding($name." ",'UTF-8,ISO-8859-1') == 'UTF-8' ? utf8_decode($name) : $name )] = (mb_detect_encoding($value." ",'UTF-8,ISO-8859-1') == 'UTF-8' ? utf8_decode($value) : $value );
}

return $array_temp;
}
[email protected]
17 年前
更好的转换方法是使用iconv,请参阅https://php.net/iconv -- 示例

<?php
$myUnicodeString
= "Åäö";
echo
iconv("UTF-8", "ISO-8859-1", $myUnicodeString);
?>

以上将以ISO-8859-1编码输出给定变量,您可以将其替换为您喜欢的任何编码。

解决字符显示错误的另一种解决方案是简单地将文档发送为UTF-8,当然还要发送UTF-8数据

<?php
# 将text/html替换为您喜欢的任何MIME类型。
header("Content-Type: text/html; charset=utf-8");
?>
MARC13
17 年前
我编写了这个函数来转换来自AJAX调用的数据以插入到我的数据库中。
它将XMLHttpRequest()中的UTF-8转换为我在LATIN2 MySQL数据库中使用的ISO-8859-2。

<?php
function utf2iso($tekst)
{
$nowytekst = str_replace("%u0104","\xA1",$tekst); //Ą
$nowytekst = str_replace("%u0106","\xC6",$nowytekst); //Ć
$nowytekst = str_replace("%u0118","\xCA",$nowytekst); //Ę
$nowytekst = str_replace("%u0141","\xA3",$nowytekst); //Ł
$nowytekst = str_replace("%u0143","\xD1",$nowytekst); //Ń
$nowytekst = str_replace("%u00D3","\xD3",$nowytekst); //Ó
$nowytekst = str_replace("%u015A","\xA6",$nowytekst); //Ś
$nowytekst = str_replace("%u0179","\xAC",$nowytekst); //Ź
$nowytekst = str_replace("%u017B","\xAF",$nowytekst); //Ż

$nowytekst = str_replace("%u0105","\xB1",$nowytekst); //ą
$nowytekst = str_replace("%u0107","\xE6",$nowytekst); //ć
$nowytekst = str_replace("%u0119","\xEA",$nowytekst); //ę
$nowytekst = str_replace("%u0142","\xB3",$nowytekst); //ł
$nowytekst = str_replace("%u0144","\xF1",$nowytekst); //ń
$nowytekst = str_replace("%u00D4","\xF3",$nowytekst); //ó
$nowytekst = str_replace("%u015B","\xB6",$nowytekst); //ś
$nowytekst = str_replace("%u017A","\xBC",$nowytekst); //ź
$nowytekst = str_replace("%u017C","\xBF",$nowytekst); //ż

return ($nowytekst);
}
?>

在我的情况下,处理AJAX调用的代码文件也必须使用UTF-8编码。
[email protected]
17 年前
简单的UTF-8到HTML转换

function utf8_to_html ($data)
{
return preg_replace("/([\\xC0-\\xF7]{1,1}[\\x80-\\xBF]+)/e", '_utf8_to_html("\\1")', $data);
}

function _utf8_to_html ($data)
{
$ret = 0;
foreach((str_split(strrev(chr((ord($data{0}) % 252 % 248 % 240 % 224 % 192) + 128) . substr($data, 1)))) as $k => $v)
$ret += (ord($v) % 128) * pow(64, $k);
return "&#$ret;";
}

示例
echo utf8_to_html("a b č ć ž こ に ち わ ()[]{}!#$?*");

输出
a b &#269; &#263; &#382; &#12371; &#12395; &#12385; &#12431; ()[]{}!#$?*
[email protected]
21年前
对转换函数utf82iso88592和iso88592tutf8的更正。
Janusz忘记了“&#324;”和“&#380;”在某些地方与“&#378;”互换。

GTo

function utf82iso88592($tekscik) {


$tekscik = str_replace("\xC4\x85", "&#261;", $tekscik);
$tekscik = str_replace("\xC4\x84", '&#260;', $tekscik);
$tekscik = str_replace("\xC4\x87", '&#263;', $tekscik);
$tekscik = str_replace("\xC4\x86", '&#262;', $tekscik);
$tekscik = str_replace("\xC4\x99", '&#281;', $tekscik);
$tekscik = str_replace("\xC4\x98", '&#280;', $tekscik);
$tekscik = str_replace("\xC5\x82", '&#322;', $tekscik);
$tekscik = str_replace("\xC5\x81", '&#321;', $tekscik);
$tekscik = str_replace("\xC5\x84", '&#324;', $tekscik);
$tekscik = str_replace("\xC5\x83", '&#323;', $tekscik);
$tekscik = str_replace("\xC3\xB3", '?', $tekscik);
$tekscik = str_replace("\xC3\x93", '?', $tekscik);
$tekscik = str_replace("\xC5\x9B", '&#347;', $tekscik);
$tekscik = str_replace("\xC5\x9A", '&#346;', $tekscik);
$tekscik = str_replace("\xC5\xBC", '&#380;', $tekscik);
$tekscik = str_replace("\xC5\xBB", '&#379;', $tekscik);
$tekscik = str_replace("\xC5\xBA", '&#378;', $tekscik);
$tekscik = str_replace("\xC5\xB9", '&#377;', $tekscik);
return $tekscik;
} // utf82iso88592

函数 iso885922utf8($tekscik) {
$tekscik = str_replace("&#261;", "\xC4\x85", $tekscik);
$tekscik = str_replace('&#260;', "\xC4\x84", $tekscik);
$tekscik = str_replace('&#263;', "\xC4\x87", $tekscik);
$tekscik = str_replace('&#262;', "\xC4\x86", $tekscik);
$tekscik = str_replace('&#281;', "\xC4\x99", $tekscik);
$tekscik = str_replace('&#280;', "\xC4\x98", $tekscik);
$tekscik = str_replace('&#322;', "\xC5\x82", $tekscik);
$tekscik = str_replace('&#321;', "\xC5\x81", $tekscik);
$tekscik = str_replace('&#324;', "\xC5\x84", $tekscik);
$tekscik = str_replace('&#323;',"\xC5\x83", $tekscik);
$tekscik = str_replace('?', "\xC3\xB3", $tekscik);
$tekscik = str_replace('?', "\xC3\x93", $tekscik);
$tekscik = str_replace('&#347;', "\xC5\x9B", $tekscik);
$tekscik = str_replace('&#346;', "\xC5\x9A", $tekscik);
$tekscik = str_replace('&#380;', "\xC5\xBC", $tekscik);
$tekscik = str_replace('&#379;', "\xC5\xBB", $tekscik);
$tekscik = str_replace('&#378;', "\xC5\xBA", $tekscik);
$tekscik = str_replace('&#377;', "\xC5\xB9", $tekscik);
return $tekscik;
} // iso885922utf8
kode68
8 年前
更新来自 okx dot oliver dot koenig at gmail dot com 的 PHP 5.6 的答案,因为 e/ 修饰符已弃用

// 这最终帮助我完成了工作,感谢Blackbit,不得不修改已弃用的ereg
// 原始注释:“Squirrelmail在源代码中包含一个将Unicode转换为实体的不错函数:”

函数 charset_decode_utf_8($string)
{
/* 只有在存在8位字符时才执行缓慢的转换 */
如果 (!preg_match("/[\200-\237]/", $string) && !preg_match("/[\241-\377]/", $string) )
return $string;

// 解码三字节Unicode字符
$string = preg_replace_callback("/([\340-\357])([\200-\277])([\200-\277])/",
create_function('$matches', 'return \'&#\'.((ord($matches[1])-224)*4096+(ord($matches[2])-128)*64+(ord($matches[3])-128)).\';\';'),
$string);

// 解码两字节Unicode字符
$string = preg_replace_callback("/([\300-\337])([\200-\277])/",
create_function('$matches', 'return \'&#\'.((ord($matches[1])-192)*64+(ord($matches[2])-128)).\';\';'),
$string);

return $string;
}

享受
visus at portsonline dot net
17 年前
以下代码帮助我处理混合(UTF8+ISO-8859-1(x))编码。在这种情况下,我拥有由不关心编码的设计师创建和维护的模板文件,以及使用 utf8_binary_ci 编码的 MySQL 数据表。

<?php

Helper
{
函数
strSplit($text, $split = 1)
{
如果 (!
is_string($text)) 返回 false;
如果 (!
is_numeric($split) && $split < 1) 返回 false;

$len = strlen($text);

$array = 数组();

$i = 0;

当 (
$i < $len)
{
$key = NULL;

对于 (
$j = 0; $j < $split; $j += 1)
{
$key .= $text{$i};

$i += 1;
}

$array[] = $key;
}

返回
$array;
}

函数
UTF8ToHTML($str)
{
$search = 数组();
$search[] = "/([\\xC0-\\xF7]{1,1}[\\x80-\\xBF]+)/e";
$search[] = "/&#228;/";
$search[] = "/&#246;/";
$search[] = "/&#252;/";
$search[] = "/&#196;/";
$search[] = "/&#214;/";
$search[] = "/&#220;/";
$search[] = "/&#223;/";

$replace = 数组();
$replace[] = 'Helper::_UTF8ToHTML("\\1")';
$replace[] = "ä";
$replace[] = "ö";
$replace[] = "ü";
$replace[] = "Ä";
$replace[] = "Ö";
$replace[] = "ü";
$replace[] = "ß";

$str = preg_replace($search, $replace, $str);

返回
$str;
}

函数
_UTF8ToHTML($str)
{
$ret = 0;

对于每个((
Helper::strSplit(strrev(chr((ord($str{0}) % 252 % 248 % 240 % 224 % 192) + 128).substr($str, 1)))) 作为 $k => $v)
$ret += (ord($v) % 128) * pow(64, $k);
返回
"&#".$ret.";";
}
}

// 用法示例:

$tpl = file_get_contents("template.tpl");
/* ... */
$row = mysql_fetch_assoc($result);

打印(
Helper::UTF8ToHTML(str_replace("{VAR}", $row['var'], $tpl)));

?>
paul.hayes at entropedia.co.uk
18 年前
我注意到下面的 utf-8 到 html 函数仅适用于 2 字节长的代码。好吧,我想要 3 字节的支持(抱歉,还没有完成 4、5 或 6)。我还注意到字符代码的连接确实有十六进制前缀 0x,因此在大型 2 字节代码中失败了)

<?
公共函数 utf2html(&$str) {

$ret = "";
$max = strlen($str);
$last = 0; // 保留最后一个常规字符的索引
对于 ($i=0; $i<$max; $i++) {
$c = $str{$i};
$c1 = ord($c);
如果 ($c1>>5 == 6) { // 110x xxxx,110 是 2 字节 unicode 的前缀
$ret .= substr($str, $last, $i-$last); // 附加我们传递的所有常规字符
$c1 &= 31; // 删除 3 位两字节前缀
$c2 = ord($str{++$i}); // 下一个字节
$c2 &= 63; // 删除 2 位尾随字节前缀
$c2 |= (($c1 & 3) << 6); // c1 的最后 2 位成为 c2 的前 2 位
$c1 >>= 2; // c1 向右移动 2 位
$ret .= "&#" . ($c1 * 0x100 + $c2) . ";"; // 这是最快的字符串连接
$last = $i+1;
}
否则如果 ($c1>>4 == 14) { // 1110 xxxx,110 是 3 字节 unicode 的前缀
$ret .= substr($str, $last, $i-$last); // 附加我们传递的所有常规字符
$c2 = ord($str{++$i}); // 下一个字节
$c3 = ord($str{++$i}); // 第三个字节
$c1 &= 15; // 删除 4 位三字节前缀
$c2 &= 63; // 删除 2 位尾随字节前缀
$c3 &= 63; // 删除 2 位尾随字节前缀
$c3 |= (($c2 & 3) << 6); // c2 的最后 2 位成为 c3 的前 2 位
$c2 >>=2; //c2 向右移动 2 位
$c2 |= (($c1 & 15) << 4); // c1 的最后 4 位成为 c2 的前 4 位
$c1 >>= 4; // c1 向右移动 4 位
$ret .= '&#' . (($c1 * 0x10000) + ($c2 * 0x100) + $c3) . ';'; // 这是最快的字符串连接
$last = $i+1;
}
}
$str=$ret . substr($str, $last, $i); // 附加最后一批常规字符
}
?>
php-net at ---NOSPAM---lc dot yi dot org
18 年前
我刚刚创建了这段代码片段来改进我的一个网站发送的用户可自定义电子邮件。

目标是使用 UTF-8(Unicode),以便非英语用户可以获得所有 Unicode 优势,但也让英语(或更具体地说,英语 MS-Outlook 用户)的生活变得无缝。问题:2003 年之前的 Outlook (?) 没有正确检测 unicode 电子邮件。当从 MS Word 中粘贴“智能引号”并以 Unicode 格式保存,然后通过电子邮件发送给 Outlook 用户时,这些字符通常被错误地渲染为“希腊语”。

因此,以下代码片段将一些策略性字符替换为 html 实体,Outlook XP(以及可能更早的版本)将按预期呈现。[代码基于此页面和 htmlenties 页面上先前帖子的代码片段]


<?php
$badwordchars
=array(
"\xe2\x80\x98", // 左单引号
"\xe2\x80\x99", // 右单引号
"\xe2\x80\x9c", // 左双引号
"\xe2\x80\x9d", // 右双引号
"\xe2\x80\x94", // em 破折号
"\xe2\x80\xa6" // 省略号
);
$fixedwordchars=array(
"&#8216;",
"&#8217;",
'&#8220;',
'&#8221;',
'&mdash;',
'&#8230;'
);
$html=str_replace($badwordchars,$fixedwordchars,$html);
?>
Blackbit
16 年前
Squirrelmail 的源代码中包含一个将 Unicode 转换为实体的实用函数。

<?php
function charset_decode_utf_8 ($string) {
/* 只有在存在 8 位字符时才执行缓慢的转换 */
/* 避免在 ereg 范围中使用 0xA0 (\240)。RH73 不喜欢那样 */
if (! ereg("[\200-\237]", $string) and ! ereg("[\241-\377]", $string))
return
$string;

// 解码三个字节的 Unicode 字符
$string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e", \
"'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'", \
$string);

// 解码两个字节的 Unicode 字符
$string = preg_replace("/([\300-\337])([\200-\277])/e", \
"'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'", \
$string);

return
$string;
}
?>
Sadi
17 年前
再次关于波兰语字母。如果您使用 fananf 的解决方案,请确保 PHP 文件使用 cp1250 编码,否则它将无法工作。这很明显,但是我在最终弄清楚之前花了一些时间,所以我想在这里发布一下。
rasmus at flajm dot se
19年前
如果您没有安装多字节扩展,这里有一个函数可以解码 UTF-16 编码的字符串。它支持无 BOM 和有 BOM 的字符串(大端和小端字节序)。

<?php
/**
* 解码 UTF-16 编码的字符串。
*
* 可以处理有 BOM 和无 BOM 的数据。
* 如果没有 BOM,则假设为大端字节序。
*
* @param string $str 要解码的 UTF-16 编码数据。
* @return string UTF-8 / ISO 编码数据。
* @access public
* @version 0.1 / 2005-01-19
* @author Rasmus Andersson {@link http://rasmusandersson.se/}
* @package Groupies
*/
function utf16_decode( $str ) {
if(
strlen($str) < 2 ) return $str;
$bom_be = true;
$c0 = ord($str{0});
$c1 = ord($str{1});
if(
$c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); }
elseif(
$c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; }
$len = strlen($str);
$newstr = '';
for(
$i=0;$i<$len;$i+=2) {
if(
$bom_be ) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); }
else {
$val = ord($str{$i+1}) << 4; $val += ord($str{$i}); }
$newstr .= ($val == 0x228) ? "\n" : chr($val);
}
return
$newstr;
}
?>
Ajgor
17 年前
波兰语解码的小幅升级

function utf82iso88592($text) {
$text = str_replace("\xC4\x85", 'ą', $text);
$text = str_replace("\xC4\x84", 'Ą', $text);
$text = str_replace("\xC4\x87", 'ć', $text);
$text = str_replace("\xC4\x86", 'Ć', $text);
$text = str_replace("\xC4\x99", 'ę', $text);
$text = str_replace("\xC4\x98", 'Ę', $text);
$text = str_replace("\xC5\x82", 'ł', $text);
$text = str_replace("\xC5\x81", 'Ł', $text);
$text = str_replace("\xC3\xB3", 'ó', $text);
$text = str_replace("\xC3\x93", 'Ó', $text);
$text = str_replace("\xC5\x9B", 'ś', $text);
$text = str_replace("\xC5\x9A", 'Ś', $text);
$text = str_replace("\xC5\xBC", 'ż', $text);
$text = str_replace("\xC5\xBB", 'Ż', $text);
$text = str_replace("\xC5\xBA", 'ż', $text);
$text = str_replace("\xC5\xB9", 'Ż', $text);
$text = str_replace("\xc5\x84", 'ń', $text);
$text = str_replace("\xc5\x83", 'Ń', $text);

return $text;
} // utf82iso88592
2ge at NO2geSPAM dot us
18 年前
大家好,

我喜欢使用友好的(好看的)URI,例如:http://example.com/try-something
我使用 UTF8 作为输入,所以我必须编写一个 UTF8toASCII 函数来获得友好的 URI。这是我想到的。

<?php
function urlize($url) {
$search = array('/[^a-z0-9]/', '/--+/', '/^-+/', '/-+$/' );
$replace = array( '-', '-', '', '');
return
preg_replace($search, $replace, utf2ascii($url));
}

function
utf2ascii($string) {
$iso88591 = "\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE6\\xE7";
$iso88591 .= "\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF";
$iso88591 .= "\\xF0\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF7";
$iso88591 .= "\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF";
$ascii = "aaaaaaaceeeeiiiidnooooooouuuuyyy";
return
strtr(mb_strtolower(utf8_decode($string), 'ISO-8859-1'),$iso88591,$ascii);
}

echo
urlize("Fucking ?m?l");

?>

希望这对某些人有所帮助。
haugas at gmail dot com
16 年前
如果您不确定字符串编码的次数,可以使用此函数

<?php

function _utf8_decode($string)
{
$tmp = $string;
$count = 0;
while (
mb_detect_encoding($tmp)=="UTF-8")
{
$tmp = utf8_decode($tmp);
$count++;
}

for (
$i = 0; $i < $count-1 ; $i++)
{
$string = utf8_decode($string);

}
return
$string;

}

?>
yannikh at gmeil dot com
18 年前
我不得不解决一个非常有趣的问题

我想用其字母替换文本中的所有 \xXX。不幸的是,XX 是 ASCII 而不是 utf8。我这样解决了我的问题
<?php preg_replace ('/\\\\x([0-9a-fA-F]{2})/e', "pack('H*',utf8_decode('\\1'))",$v); ?>
fhoech
19年前
抱歉,我在上一条评论中打错了字。已更正正则表达式

^([\\x00-\\x7f]|
[\\xc2-\\xdf][\\x80-\\xbf]|
\\xe0[\\xa0-\\xbf][\\x80-\\xbf]|
[\\xe1-\\xec][\\x80-\\xbf]{2}|
\\xed[\\x80-\\x9f][\\x80-\\xbf]|
\\xef[\\x80-\\xbf][\\x80-\\xbd]|
\\xee[\\x80-\\xbf]{2}|
\xf0[\\x90-\\xbf][\\x80-\\xbf]{2}|
[\\xf1-\\xf3][\\x80-\\xbf]{3}|
\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2})*$
tobias at code-x dot de
18 年前
将 uft8-html 符号 &#301; 转换为 uft8

<?
function uft8html2utf8( $s ) {
if ( !function_exists('uft8html2utf8_callback') ) {
function uft8html2utf8_callback($t) {
$dec = $t[1];
if ($dec < 128) {
$utf = chr($dec);
} else if ($dec < 2048) {
$utf = chr(192 + (($dec - ($dec % 64)) / 64));
$utf .= chr(128 + ($dec % 64));
} else {
$utf = chr(224 + (($dec - ($dec % 4096)) / 4096));
$utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64));
$utf .= chr(128 + ($dec % 64));
}
return $utf;
}
}
return preg_replace_callback('|&#([0-9]{1,});|', 'uft8html2utf8_callback', $s );
}
echo uft8html2utf8('test: &#301;');
?>
To Top