PHPのお勉強!

PHP TOP

mb_convert_encoding

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

mb_convert_encodingある文字エンコーディングの文字列を、別の文字エンコーディングに変換する

説明

mb_convert_encoding(array|string $string, string $to_encoding, array|string|null $from_encoding = null): array|string|false

文字列 string の文字エンコーディングを、 from_encoding または現在の内部エンコーディングから to_encoding に変換します。 string が配列の場合、それに含まれる全ての文字列型の値が再帰的に変換されます。

パラメータ

string

変換する string または array

to_encoding

変換したい文字エンコーディング。

from_encoding

string を解釈するのに使われている 現在の文字エンコーディング。 配列またはカンマ区切りの文字列とすることで、 複数のエンコーディングを指定できます。 この場合、正しいエンコーディングを mb_detect_encoding() と同じアルゴリズムで推測します。

from_encoding が省略されたり、 null だった場合は、 mbstring.internal_encoding setting が設定されていた場合、それを使います。 設定されていない場合は、 default_charset setting を使います。

to_encodingfrom_encoding に指定できる値は、 サポートされる文字エンコーディングを参照ください。

戻り値

成功時に、変換後の文字列または配列を返します。 失敗した場合に false を返します

エラー / 例外

PHP 8.0.0 以降では、 to_encoding または from_encoding に不正なエンコーディングが渡された場合、 ValueError がスローされるようになりました。 これより前のバージョンでは、 E_WARNING が発生していました。

変更履歴

バージョン 説明
8.2.0 mb_convert_encoding() は、 以下のテキストでないエンコーディングを返さなくなりました: "Base64", "QPrint", "UUencode", "HTML entities", "7 bit", "8 bit"
8.0.0 to_encoding に不正なエンコーディングが渡された場合、 ValueError がスローされるようになりました。
8.0.0 from_encoding に不正なエンコーディングが渡された場合、 ValueError がスローされるようになりました。
8.0.0 from_encoding は、nullable になりました。
7.2.0 この関数は、 string に 配列を受け入れるようになりました。 これより前のバージョンでは、文字列のみがサポートされていました。

例1 mb_convert_encoding() の例

<?php
/* 内部文字エンコーディングからSJISに変換 */
$str = mb_convert_encoding($str, "SJIS");

/* EUC-JPからUTF-7に変換 */
$str = mb_convert_encoding($str, "UTF-7", "EUC-JP");

/* JIS, eucjp-win, sjis-winの順番で自動検出し、UCS-2LEに変換 */
$str = mb_convert_encoding($str, "UCS-2LE", "JIS, eucjp-win, sjis-win");

/* mbstring.language が "Japanese" の場合 "auto" は、"ASCII,JIS,UTF-8,EUC-JP,SJIS" に展開される */
$str = mb_convert_encoding($str, "EUC-JP", "auto");
?>

参考

  • mb_detect_order() - 文字エンコーディング検出順序を設定あるいは取得する
  • UConverter::transcode() - ある文字エンコーディングから別の文字エンコーディングに文字列を変換する
  • iconv() - ある文字エンコーディングの文字列を、別の文字エンコーディングに変換する

add a note

User Contributed Notes 30 notes

up
71
josip at cubrad dot com
11 years ago
For my last project I needed to convert several CSV files from Windows-1250 to UTF-8, and after several days of searching around I found a function that is partially solved my problem, but it still has not transformed all the characters. So I made ​​this:

function w1250_to_utf8($text) {
// map based on:
// http://konfiguracja.c0.pl/iso02vscp1250en.html
// http://konfiguracja.c0.pl/webpl/index_en.html#examp
// http://www.htmlentities.com/html/entities/
$map = array(
chr(0x8A) => chr(0xA9),
chr(0x8C) => chr(0xA6),
chr(0x8D) => chr(0xAB),
chr(0x8E) => chr(0xAE),
chr(0x8F) => chr(0xAC),
chr(0x9C) => chr(0xB6),
chr(0x9D) => chr(0xBB),
chr(0xA1) => chr(0xB7),
chr(0xA5) => chr(0xA1),
chr(0xBC) => chr(0xA5),
chr(0x9F) => chr(0xBC),
chr(0xB9) => chr(0xB1),
chr(0x9A) => chr(0xB9),
chr(0xBE) => chr(0xB5),
chr(0x9E) => chr(0xBE),
chr(0x80) => '&euro;',
chr(0x82) => '&sbquo;',
chr(0x84) => '&bdquo;',
chr(0x85) => '&hellip;',
chr(0x86) => '&dagger;',
chr(0x87) => '&Dagger;',
chr(0x89) => '&permil;',
chr(0x8B) => '&lsaquo;',
chr(0x91) => '&lsquo;',
chr(0x92) => '&rsquo;',
chr(0x93) => '&ldquo;',
chr(0x94) => '&rdquo;',
chr(0x95) => '&bull;',
chr(0x96) => '&ndash;',
chr(0x97) => '&mdash;',
chr(0x99) => '&trade;',
chr(0x9B) => '&rsquo;',
chr(0xA6) => '&brvbar;',
chr(0xA9) => '&copy;',
chr(0xAB) => '&laquo;',
chr(0xAE) => '&reg;',
chr(0xB1) => '&plusmn;',
chr(0xB5) => '&micro;',
chr(0xB6) => '&para;',
chr(0xB7) => '&middot;',
chr(0xBB) => '&raquo;',
);
return html_entity_decode(mb_convert_encoding(strtr($text, $map), 'UTF-8', 'ISO-8859-2'), ENT_QUOTES, 'UTF-8');
}
up
10
Julian Egelstaff
1 year ago
If you have what looks like ISO-8859-1, but it includes "smart quotes" courtesy of Microsoft software, or people cutting and pasting content from Microsoft software, then what you're actually dealing with is probably Windows-1252. Try this:

<?php
$cleanText
= mb_convert_encoding($text, 'UTF-8', 'Windows-1252');
?>

The annoying part is that the auto detection (ie: the mb_detect_encoding function) will often think Windows-1252 is ISO-8859-1. Close, but no cigar. This is critical if you're then trying to do unserialize on the resulting text, because the byte count of the string needs to be perfect.
up
40
regrunge at hotmail dot it
14 years ago
I've been trying to find the charset of a norwegian (with a lot of ø, æ, å) txt file written on a Mac, i've found it in this way:

<?php
$text
= "A strange string to pass, maybe with some ø, æ, å characters.";

foreach(
mb_list_encodings() as $chr){
echo
mb_convert_encoding($text, 'UTF-8', $chr)." : ".$chr."<br>";
}
?>

The line that looks good, gives you the encoding it was written in.

Hope can help someone
up
31
volker at machon dot biz
17 years ago
Hey guys. For everybody who's looking for a function that is converting an iso-string to utf8 or an utf8-string to iso, here's your solution:

public function encodeToUtf8($string) {
return mb_convert_encoding($string, "UTF-8", mb_detect_encoding($string, "UTF-8, ISO-8859-1, ISO-8859-15", true));
}

public function encodeToIso($string) {
return mb_convert_encoding($string, "ISO-8859-1", mb_detect_encoding($string, "UTF-8, ISO-8859-1, ISO-8859-15", true));
}

For me these functions are working fine. Give it a try
up
4
Rainer Perske
2 years ago
Text-encoding HTML-ENTITIES will be deprecated as of PHP 8.2.

To convert all non-ASCII characters into entities (to produce pure 7-bit HTML output), I was using:

<?php
echo mb_convert_encoding( htmlspecialchars( $text, ENT_QUOTES, 'UTF-8' ), 'HTML-ENTITIES', 'UTF-8' );
?>

I can get the identical result with:

<?php
echo mb_encode_numericentity( htmlentities( $text, ENT_QUOTES, 'UTF-8' ), [0x80, 0x10FFFF, 0, ~0], 'UTF-8' );
?>

The output contains well-known named entities for some often used characters and numeric entities for the rest.
up
11
francois at bonzon point com
15 years ago
aaron, to discard unsupported characters instead of printing a ?, you might as well simply set the configuration directive:

mbstring.substitute_character = "none"

in your php.ini. Be sure to include the quotes around none. Or at run-time with

<?php
ini_set
('mbstring.substitute_character', "none");
?>
up
14
aaron at aarongough dot com
15 years ago
My solution below was slightly incorrect, so here is the correct version (I posted at the end of a long day, never a good idea!)

Again, this is a quick and dirty solution to stop mb_convert_encoding from filling your string with question marks whenever it encounters an illegal character for the target encoding.

<?php
function convert_to ( $source, $target_encoding )
{
// detect the character encoding of the incoming file
$encoding = mb_detect_encoding( $source, "auto" );

// escape all of the question marks so we can remove artifacts from
// the unicode conversion process
$target = str_replace( "?", "[question_mark]", $source );

// convert the string to the target encoding
$target = mb_convert_encoding( $target, $target_encoding, $encoding);

// remove any question marks that have been introduced because of illegal characters
$target = str_replace( "?", "", $target );

// replace the token string "[question_mark]" with the symbol "?"
$target = str_replace( "[question_mark]", "?", $target );

return
$target;
}
?>

Hope this helps someone! (Admins should feel free to delete my previous, incorrect, post for clarity)
-A
up
9
eion at bigfoot dot com
18 years ago
many people below talk about using
<?php
mb_convert_encode
($s,'HTML-ENTITIES','UTF-8');
?>
to convert non-ascii code into html-readable stuff. Due to my webserver being out of my control, I was unable to set the database character set, and whenever PHP made a copy of my $s variable that it had pulled out of the database, it would convert it to nasty latin1 automatically and not leave it in it's beautiful UTF-8 glory.

So [insert korean characters here] turned into ?????.

I found myself needing to pass by reference (which of course is deprecated/nonexistent in recent versions of PHP)
so instead of
<?php
mb_convert_encode
(&$s,'HTML-ENTITIES','UTF-8');
?>
which worked perfectly until I upgraded, so I had to use
<?php
call_user_func_array
('mb_convert_encoding', array(&$s,'HTML-ENTITIES','UTF-8'));
?>

Hope it helps someone else out
up
3
Stephan van der Feest
19 years ago
To add to the Flash conversion comment below, here's how I convert back from what I've stored in a database after converting from Flash HTML text field output, in order to load it back into a Flash HTML text field:

function htmltoflash($htmlstr)
{
return str_replace("&lt;br /&gt;","\n",
str_replace("<","&lt;",
str_replace(">","&gt;",
mb_convert_encoding(html_entity_decode($htmlstr),
"UTF-8","ISO-8859-1"))));
}
up
3
urko at wegetit dot eu
12 years ago
If you are trying to generate a CSV (with extended chars) to be opened at Exel for Mac, the only that worked for me was:
<?php mb_convert_encoding( $CSV, 'Windows-1252', 'UTF-8'); ?>

I also tried this:

<?php
//Separado OK, chars MAL
iconv('MACINTOSH', 'UTF8', $CSV);
//Separado MAL, chars OK
chr(255).chr(254).mb_convert_encoding( $CSV, 'UCS-2LE', 'UTF-8');
?>

But the first one didn't show extended chars correctly, and the second one, did't separe fields correctly
up
1
me at gsnedders dot com
15 years ago
It appears that when dealing with an unknown "from encoding" the function will both throw an E_WARNING and proceed to convert the string from ISO-8859-1 to the "to encoding".
up
1
vasiliauskas dot agnius at gmail dot com
6 years ago
When you need to convert from HTML-ENTITIES, but your UTF-8 string is partially broken (not all chars in UTF-8) - in this case passing string to mb_convert_encoding($string, 'UTF-8', 'HTML-ENTITIES'); - corrupts chars in string even more. In this case you need to replace html entities gradually to preserve character good encoding. I wrote such closure for this job :
<?php
$decode_entities
= function($string) {
preg_match_all("/&#?\w+;/", $string, $entities, PREG_SET_ORDER);
$entities = array_unique(array_column($entities, 0));
foreach (
$entities as $entity) {
$decoded = mb_convert_encoding($entity, 'UTF-8', 'HTML-ENTITIES');
$string = str_replace($entity, $decoded, $string);
}
return
$string;
};
?>
up
2
Daniel Trebbien
15 years ago
Note that `mb_convert_encoding($val, 'HTML-ENTITIES')` does not escape '\'', '"', '<', '>', or '&'.
up
1
katzlbtjunk at hotmail dot com
16 years ago
Clean a string for use as filename by simply replacing all unwanted characters with underscore (ASCII converts to 7bit). It removes slightly more chars than necessary. Hope its useful.

$fileName = 'Test:!"$%&/()=ÖÄÜöäü<<';
echo strtr(mb_convert_encoding($fileName,'ASCII'),
' ,;:?*#!§$%&/(){}<>=`´|\\\'"',
'____________________________');
up
1
bmxmale at qwerty dot re
2 years ago
/**
* Convert Windows-1250 to UTF-8
* Based on https://www.php.net/manual/en/function.mb-convert-encoding.php#112547
*/
class TextConverter
{
private const ENCODING_TO = 'UTF-8';
private const ENCODING_FROM = 'ISO-8859-2';

private array $mapChrChr = [
0x8A => 0xA9,
0x8C => 0xA6,
0x8D => 0xAB,
0x8E => 0xAE,
0x8F => 0xAC,
0x9C => 0xB6,
0x9D => 0xBB,
0xA1 => 0xB7,
0xA5 => 0xA1,
0xBC => 0xA5,
0x9F => 0xBC,
0xB9 => 0xB1,
0x9A => 0xB9,
0xBE => 0xB5,
0x9E => 0xBE
];

private array $mapChrString = [
0x80 => '&euro;',
0x82 => '&sbquo;',
0x84 => '&bdquo;',
0x85 => '&hellip;',
0x86 => '&dagger;',
0x87 => '&Dagger;',
0x89 => '&permil;',
0x8B => '&lsaquo;',
0x91 => '&lsquo;',
0x92 => '&rsquo;',
0x93 => '&ldquo;',
0x94 => '&rdquo;',
0x95 => '&bull;',
0x96 => '&ndash;',
0x97 => '&mdash;',
0x99 => '&trade;',
0x9B => '&rsquo;',
0xA6 => '&brvbar;',
0xA9 => '&copy;',
0xAB => '&laquo;',
0xAE => '&reg;',
0xB1 => '&plusmn;',
0xB5 => '&micro;',
0xB6 => '&para;',
0xB7 => '&middot;',
0xBB => '&raquo;'
];

/**
* @param $text
* @return string
*/
public function execute($text): string
{
$map = $this->prepareMap();

return html_entity_decode(
mb_convert_encoding(strtr($text, $map), self::ENCODING_TO, self::ENCODING_FROM),
ENT_QUOTES,
self::ENCODING_TO
);
}

/**
* @return array
*/
private function prepareMap(): array
{
$maps[] = $this->arrayMapAssoc(function ($k, $v) {
return [chr($k), chr($v)];
}, $this->mapChrChr);

$maps[] = $this->arrayMapAssoc(function ($k, $v) {
return [chr($k), $v];
}, $this->mapChrString);

return array_merge([], ...$maps);
}

/**
* @param callable $function
* @param array $array
* @return array
*/
private function arrayMapAssoc(callable $function, array $array): array
{
return array_column(
array_map(
$function,
array_keys($array),
$array
),
1,
0
);
}
}
up
0
chzhang at gmail dot com
15 years ago
instead of ini_set(), you can try this

mb_substitute_character("none");
up
0
lanka at eurocom dot od dot ua
21 years ago
Another sample of recoding without MultiByte enabling.
(Russian koi->win, if input in win-encoding already, function recode() returns unchanged string)

<?php
// 0 - win
// 1 - koi
function detect_encoding($str) {
$win = 0;
$koi = 0;

for(
$i=0; $i<strlen($str); $i++) {
if(
ord($str[$i]) >224 && ord($str[$i]) < 255) $win++;
if(
ord($str[$i]) >192 && ord($str[$i]) < 223) $koi++;
}

if(
$win < $koi ) {
return
1;
} else return
0;

}

// recodes koi to win
function koi_to_win($string) {

$kw = array(128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 254, 224, 225, 246, 228, 229, 244, 227, 245, 232, 233, 234, 235, 236, 237, 238, 239, 255, 240, 241, 242, 243, 230, 226, 252, 251, 231, 248, 253, 249, 247, 250, 222, 192, 193, 214, 196, 197, 212, 195, 213, 200, 201, 202, 203, 204, 205, 206, 207, 223, 208, 209, 210, 211, 198, 194, 220, 219, 199, 216, 221, 217, 215, 218);
$wk = array(128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 225, 226, 247, 231, 228, 229, 246, 250, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243, 244, 245, 230, 232, 227, 254, 251, 253, 255, 249, 248, 252, 224, 241, 193, 194, 215, 199, 196, 197, 214, 218, 201, 202, 203, 204, 205, 206, 207, 208, 210, 211, 212, 213, 198, 200, 195, 222, 219, 221, 223, 217, 216, 220, 192, 209);

$end = strlen($string);
$pos = 0;
do {
$c = ord($string[$pos]);
if (
$c>128) {
$string[$pos] = chr($kw[$c-128]);
}

} while (++
$pos < $end);

return
$string;
}

function
recode($str) {

$enc = detect_encoding($str);
if (
$enc==1) {
$str = koi_to_win($str);
}

return
$str;
}
?>
up
-1
nicole
8 years ago
// convert UTF8 to DOS = CP850
//
// $utf8_text=UTF8-Formatted text;
// $dos=CP850-Formatted text;

// have fun

$dos = mb_convert_encoding($utf8_text, "CP850", mb_detect_encoding($utf8_text, "UTF-8, CP850, ISO-8859-15", true));
up
-1
Tom Class
18 years ago
Why did you use the php html encode functions? mbstring has it's own Encoding which is (as far as I tested it) much more usefull:

HTML-ENTITIES

Example:

$text = mb_convert_encoding($text, 'HTML-ENTITIES', "UTF-8");
up
-1
Daniel
8 years ago
If you are attempting to convert "UTF-8" text to "ISO-8859-1" and the result is always returning in "ASCII", place the following line of code before the mb_convert_encoding:

mb_detect_order(array('UTF-8', 'ISO-8859-1'));

It is necessary to force a specific search order for the conversion to work
up
-2
mac.com@nemo
18 years ago
For those wanting to convert from $set to MacRoman, use iconv():

<?php

$string
= iconv('UTF-8', 'macintosh', $string);

?>

('macintosh' is the IANA name for the MacRoman character set.)
up
-2
David Hull
17 years ago
As an alternative to Johannes's suggestion for converting strings from other character sets to a 7bit representation while not just deleting latin diacritics, you might try this:

<?php
$text
= iconv($from_enc, 'US-ASCII//TRANSLIT', $text);
?>

The only disadvantage is that it does not convert "ä" to "ae", but it handles punctuation and other special characters better.
--
David
up
-3
aofg
17 years ago
When converting Japanese strings to ISO-2022-JP or JIS on PHP >= 5.2.1, you can use "ISO-2022-JP-MS" instead of them.
Kishu-Izon (platform dependent) characters are converted correctly with the encoding, as same as with eucJP-win or with SJIS-win.
up
-2
jamespilcher1 - hotmail
20 years ago
be careful when converting from iso-8859-1 to utf-8.

even if you explicitly specify the character encoding of a page as iso-8859-1(via headers and strict xml defs), windows 2000 will ignore that and interpret it as whatever character set it has natively installed.

for example, i wrote char #128 into a page, with char encoding iso-8859-1, and it displayed in internet explorer (& mozilla) as a euro symbol.

it should have displayed a box, denoting that char #128 is undefined in iso-8859-1. The problem was it was displaying in "Windows: western europe" (my native character set).

this led to confusion when i tried to convert this euro to UTF-8 via mb_convert_encoding()

IE displays UTF-8 correctly- and because PHP correctly converted #128 into a box in UTF-8, IE would show a box.

so all i saw was mb_convert_encoding() converting a euro symbol into a box. It took me a long time to figure out what was going on.
up
-4
StigC
16 years ago
For the php-noobs (like me) - working with flash and php.

Here's a simple snippet of code that worked great for me, getting php to show special Danish characters, from a Flash email form:

<?php
// Name Escape
$escName = mb_convert_encoding($_POST["Name"], "ISO-8859-1", "UTF-8");

// message escape
$escMessage = mb_convert_encoding($_POST["Message"], "ISO-8859-1", "UTF-8");

// Headers.. and so on...
?>