PHPのお勉強!

PHP TOP

utf8_decode

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

utf8_decode UTF-8 エンコードされた文字列を、ISO-8859-1 に変換し、表現できない文字を置換する

警告

この関数は PHP 8.2.0 で 非推奨になります。この関数に頼らないことを強く推奨します。

説明

utf8_decode(string $string): string

この関数は、文字列 stringUTF-8 エンコードから ISO-8859-1 へ変換します。 有効な UTF-8 ではない文字列バイト、 および ISO-8859-1 に存在しない UTF-8 の文字 (つまり、U+00FF 以降のコードポイント) は、 ? に置き換えられます。

注意:

ISO-8859-1 文字エンコーディングを使っているとマークされている 多くの Web ページが、実際にはそれと似た Windows-1252 を使っており、 Web ブラウザは ISO-8859-1 Web ページを Windows-1252 として解釈しています。Windows-1252ISO-8859-1 のある制御文字の代わりに、ユーロ記号 () や curly quote ( ) を印字可能な文字として追加しています。 この関数はそうした Windows-1252 文字を正しく変換しません。 Windows-1252 の変換が必要な場合は、別の関数を使ってください。

パラメータ

string

UTF-8 エンコードされた文字列。

戻り値

string を ISO-8859-1 に変換した結果を返します。

変更履歴

バージョン 説明
8.2.0 この関数は、推奨されなくなりました。
7.2.0 この関数は、XML拡張モジュールから PHP のコアに移動しました。 これより前のバージョンでは、 この関数は XML拡張モジュール をインストールしていた場合にのみ利用可能でした。

例1 基本的な例

<?php
// Convert the string 'Zoë' from UTF-8 to ISO 8859-1
$utf8_string = "\x5A\x6F\xC3\xAB";
$iso8859_1_string = utf8_decode($utf8_string);
echo
bin2hex($iso8859_1_string), "\n";
// Invalid UTF-8 sequences are replaced with '?'
$invalid_utf8_string = "\xC3";
$iso8859_1_string = utf8_decode($invalid_utf8_string);
var_dump($iso8859_1_string);
// Characters which don't exist in ISO 8859-1, such as
// '€' (Euro Sign) are also replaced with '?'
$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 with diaeresis) in 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"; // 'λ' (Greek lower-case lambda) in 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"; // '€' (Euro sign) in UTF-8 (not present in 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ë' in 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"; // € (Euro Sign) does not exist in ISO 8859-1
$iso8859_1_string = UConverter::transcode(
$utf8_string, 'ISO-8859-1', 'UTF-8', ['to_subst' => '?']
);
var_dump($iso8859_1_string);
?>

上の例の出力は以下となります。

sring(1) "?"

参考

  • utf8_encode() - ISO-8859-1 文字列を UTF-8 に変換する
  • mb_convert_encoding() - ある文字エンコーディングの文字列を、別の文字エンコーディングに変換する
  • UConverter::transcode() - ある文字エンコーディングから別の文字エンコーディングに文字列を変換する
  • iconv() - ある文字エンコーディングの文字列を、別の文字エンコーディングに変換する

add a note

User Contributed Notes 32 notes

up
10
info at vanylla dot it
15 years ago
IMPORTANT: when converting UTF8 data that contains the EURO sign DON'T USE utf_decode function.

utf_decode converts the data into ISO-8859-1 charset. But ISO-8859-1 charset does not contain the EURO sign, therefor the EURO sign will be converted into a question mark character '?'

In order to convert properly UTF8 data with EURO sign you must use:

iconv("UTF-8", "CP1252", $data)
up
4
alexlevin at kvadro dot net
17 years ago
If you running Gentoo Linux and encounter problems with some PHP4 applications saying:
Call to undefined function: utf8_decode()
Try reemerge PHP4 with 'expat' flag enabled.
up
8
deceze at gmail dot com
13 years ago
Please note that utf8_decode simply converts a string encoded in UTF-8 to ISO-8859-1. A more appropriate name for it would be utf8_to_iso88591. If your text is already encoded in ISO-8859-1, you do not need this function. If you don't want to use ISO-8859-1, you do not need this function.

Note that UTF-8 can represent many more characters than ISO-8859-1. Trying to convert a UTF-8 string that contains characters that can't be represented in ISO-8859-1 to ISO-8859-1 will garble your text and/or cause characters to go missing. Trying to convert text that is not encoded in UTF-8 using this function will most likely garble the text.

If you need to convert any text from any encoding to any other encoding, look at iconv() instead.
up
5
gabriel arobase gabsoftware dot com
13 years ago
If you want to retrieve some UTF-8 data from your database, you don't need utf8_decode().

Simply do the following query before any SELECT :

$result = mysql_query("SET NAMES utf8");
up
4
lukasz dot mlodzik at gmail dot com
16 years ago
Update to MARC13 function utf2iso()
I'm using it to handle AJAX POST calls.
Despite using
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'; charset='utf-8');
it still code Polish letters using UTF-16

This is only for Polish letters:

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

Everything goes smooth, but it doesn't change '%u00D3','Ó' and '%u00F3','ó'. I dont have idea what to do with that.

Remember! File must be saved in UTF-8 coding.
up
2
Aleksandr
7 years ago
In addition to note by yannikh at gmeil dot com, another way to decode strings with non-latin chars from unix console like

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

The code above will output:
C=RU, L=Москва,
up
3
sam
17 years ago
In addition to yannikh's note, to convert a hex utf8 string

<?php

echo utf8_decode("\x61\xc3\xb6\x61");
// works as expected

$abc="61c3b661";
$newstr = "";
$l = strlen($abc);
for (
$i=0;$i<$l;$i+=2){
$newstr .= "\x".$abc[$i].$abc[$i+1];
}
echo
utf8_decode($newstr);
// or varieties of "\x": "\\x" etc does NOT output what you want

echo utf8_decode(pack('H*',$abc));
// this outputs the correct string, like the first line.

?>
up
2
Aidan Kehoe <php-manual at parhasard dot net>
20 years ago
The fastest way I've found to check if something is valid UTF-8 is
<?php
if (iconv('UTF-8', 'UTF-8', $input) != $input) {
/* It's not UTF-8--for me, it's probably CP1252, the Windows
version of Latin 1, with directed quotation marks and
the Euro sign. */
}
?>.
The iconv() C library fails if it's told a string is UTF-8 and it isn't; the PHP one doesn't, it just returns the conversion up to the point of failure, so you have to compare the result to the input to find out if the conversion succeeded.
up
1
j dot dittmer at portrix dot net
19 years ago
The regex in the last comment has some typos. This is a
syntactically valid one, don't know if it's correct though.
You've to concat the expression in one long line.

^(
[\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}
)*$
up
1
christoffer
12 years ago
The preferred way to use this on an array would be with the built in PHP function "array_map()", as for example:
$array = array_map("utf8_decode", $array);
up
1
thierry.bo # netcourrier point com
19 years ago
In response to fhoech (22-Sep-2005 11:55), I just tried a simultaneous test with the file UTF-8-test.txt using your regexp, 'j dot dittmer' (20-Sep-2005 06:30) regexp (message #56962), `php-note-2005` (17-Feb-2005 08:57) regexp in his message on `mb-detect-encoding` page (http://us3.php.net/manual/en/function.mb-detect-encoding.php#50087) who is using a regexp from the W3C (http://w3.org/International/questions/qa-forms-utf-8.html), and PHP mb_detect_encoding function.

Here are a summarize of the results :

201 lines are valid UTF8 strings using phpnote regexp
203 lines are valid UTF8 strings using j.dittmer regexp
200 lines are valid UTF8 strings using fhoech regexp
239 lines are valid UTF8 strings using using mb_detect_encoding

Here are the lines with differences (left to right, phpnote, j.dittmer and fhoech) :

Line #70 : NOT UTF8|IS UTF8!|IS UTF8! :2.1.1 1 byte (U-00000000): ""
Line #79 : NOT UTF8|IS UTF8!|IS UTF8! :2.2.1 1 byte (U-0000007F): ""
Line #81 : IS UTF8!|IS UTF8!|NOT UTF8 :2.2.3 3 bytes (U-0000FFFF): "&#65535;" |
Line #267 : IS UTF8!|IS UTF8!|NOT UTF8 :5.3.1 U+FFFE = ef bf be = "&#65534;" |
Line #268 : IS UTF8!|IS UTF8!|NOT UTF8 :5.3.2 U+FFFF = ef bf bf = "&#65535;" |

Interesting is that you said that your regexp corrected j.dittmer regexp that failed on 5.3 section, but it my test I have the opposite result ?!

I ran this test on windows XP with PHP 4.3.11dev. Maybe these differences come from operating system, or PHP version.

For mb_detect_encoding I used the command :

mb_detect_encoding($line, 'UTF-8, ISO-8859-1, ASCII');
up
0
jamalmarlone at gmail dot com
1 year ago
$string = "Bjørn Johansen";

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

----
prints: "Bjørn Johansen"