Php paano malalaman ang encoding mapping. Pagtukoy ng text encoding sa PHP - isang pangkalahatang-ideya ng mga kasalukuyang solusyon at isa pang bike. Ano ang dinadala ng Google

May nakita akong problema - auto-detection ng page/text/whatever encoding. Ang gawain ay hindi na bago, at maraming mga bisikleta ang naimbento na. Ang artikulo ay naglalaman ng isang maikling pangkalahatang-ideya ng kung ano ang natagpuan sa Internet - kasama ang isang panukala ng kung ano sa tingin ko ay isang karapat-dapat na solusyon.

1. Bakit hindi mb_detect_encoding()?

Sa madaling salita, hindi ito gumagana.

Panoorin natin:
// Sa pasukan - Russian text na naka-encode CP1251 $string = iconv("UTF-8", "Windows-1251", "Lumapit siya kay Anna Pavlovna, hinalikan ang kamay nito, inilantad ang kanyang mabango at nagniningning na kalbong ulo sa kanya, at mahinahong umupo. pababa sa sofa."); // Tingnan natin kung ano ang ibinibigay sa atin ng md_detect_encoding(). Unang $strict = FALSE var_dump(mb_detect_encoding($string, array("UTF-8"))); // UTF-8 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"))); // Windows-1251 var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"))); // KOI8-R var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"))); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"))); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"))); // ISO-8859-5 // Now $strict = TRUE var_dump(mb_detect_encoding($string, array("UTF-8"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"), TRUE)); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"), TRUE)); // ISO-8859-5
Tulad ng nakikita mo, ang output ay isang kumpletong gulo. Ano ang gagawin natin kapag hindi malinaw kung bakit ganito ang pagkilos ng isang function? Tama, i-Google natin. Nakakita ako ng magandang sagot.

Upang tuluyang maalis ang lahat ng pag-asa sa paggamit ng mb_detect_encoding(), kailangan mong tingnan ang source code ng extension ng mbstring. Kaya, isara ang iyong mga manggas at umalis tayo:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // line 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + click:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:643 const char* mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( const mbfl_encoding *encoding; encoding = mbfl,listz_encoding , mahigpit);
Ctrl + click:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * kilalanin ang encoding */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Hindi ko ipo-post ang buong teksto ng pamamaraan upang hindi kalat ang artikulo sa mga hindi kinakailangang mapagkukunan. Ang mga interesado ay magkakaroon ng hitsura para sa kanilang sarili. Interesado kami sa numero ng linya 593, kung saan aktwal naming tinitingnan kung tumutugma ang character sa pag-encode:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_function)(*p, filter); if (filter->flag) ( masama++; )
Narito ang mga pangunahing filter para sa single-byte Cyrillic:

Windows-1251 (napanatili ang mga orihinal na komento)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* ang pangit ng lahat ng ito ngayon! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filter) ( kung (c >= 0x80 && c< 0xff) filter->bandila = 0;

ibang filter->
KOI8-R< 0xff) filter->// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filter) ( kung (c >= 0x80 && c

bandila = 0;
iba pang filter->bandila = 1; /* hindi ito */ bumalik c; )
ISO-8859-5 (lahat ay masaya dito)

// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter) ( return c; )

Tulad ng nakikita mo, ang ISO-8859-5 ay palaging nagbabalik ng TRUE (upang ibalik ang FALSE, kailangan mong itakda ang filter->flag = 1).

Kapag tiningnan namin ang mga filter, ang lahat ay nahulog sa lugar. Walang paraan upang makilala ang CP1251 mula sa KOI8-R. Sa pangkalahatan, ang ISO-8859-5, kung ito ay nasa listahan ng mga pag-encode, ay palaging makikita bilang tama.

Sa pangkalahatan, mabibigo. Naiintindihan ito - sa pangkalahatan, imposibleng malaman ang pag-encode sa pamamagitan lamang ng mga code ng character, dahil ang mga code na ito ay nagsalubong sa iba't ibang mga pag-encode.

2. Ano ang dinadala ng Google
At inilalabas ng Google ang lahat ng uri ng kapahamakan. Hindi ko ipo-post ang pinagmulan dito, tingnan mo ang iyong sarili kung gusto mo (alisin ang puwang pagkatapos ng http://, hindi ko alam kung paano ipakita ang teksto nang walang link):

Http://deer.org.ua/2009/10/06/1/

http://php.su/forum/topic.php?forum=1&topic=1346

3. Maghanap ayon sa hub
Mga kalamangan at kahinaan sa komento sa link. Sa personal, sa palagay ko ang solusyon na ito ay kalabisan lamang para sa pag-detect ng pag-encode - lumalabas na napakalakas nito. Ang pagtukoy sa pag-encode dito ay isang side effect).

4. Actually, ang desisyon ko

Ang ideya ay lumitaw habang tinitingnan ang pangalawang link mula sa nakaraang seksyon. Ang ideya ay ang mga sumusunod: kumukuha kami ng isang malaking Russian text, sinusukat ang mga frequency ng iba't ibang mga titik, at ginagamit ang mga frequency na ito upang makita ang pag-encode. Sa hinaharap, sasabihin ko kaagad na magkakaroon ng mga problema sa malalaki at maliliit na titik. Samakatuwid, nagpo-post ako ng mga halimbawa ng mga frequency ng titik (tawagin natin itong "spectrum"), parehong case-sensitive at case-insensitive (sa pangalawang kaso, nagdagdag ako ng mas malaki sa isang maliit na titik na may parehong frequency, at inalis lahat ang mas malaki). Sa mga "spectra" na ito ang lahat ng mga titik na may mga frequency na mas mababa sa 0.001 at isang puwang ay pinutol. Ito ang nakuha ko pagkatapos iproseso ang "Digmaan at Kapayapaan":

Case-sensitive na "spectrum":
array ("o" => 0.095249209893009, "e" => 0.06836817536026, "a" => 0.067481298384992, "i" => 0.055995027400041, "n" => 2 .002252892226507, "N " => 0.0021318391371162, "P" => 0.0018574762967903, "f" => 0.0015961610948418, "B" => 0.0014044332975731, "A9" => 30. 0.0012623590130186, "K" => 0.0011804488387602, "M" => 0.001061932790165,)

Case insensitive:
array ("O" => 0.095249209893009, "o" => 0.095249209893009, "E" => 0.06836817536026, "e" => 0.06836817536026, "A" => 8.06, "A" => 8.026, "A" 67481298384992, "AT" => 0.055995027400041 , "i" => 0.055995027400041, .... "C" => 0.0029893589260344, "c" => 0.0029893589260344, "sch" => 0.00246491635014 => 6.00246491635014 "E" => 0.002252892226507, "e " => 0.002252892226507, "F" => 0.0015961610948418, "f" => 0.0015961610948418,)

Spectra sa iba't ibang pag-encode (ang mga array key ay ang mga code ng kaukulang mga character sa naaangkop na pag-encode):

Susunod. Kumuha kami ng teksto ng hindi kilalang pag-encode, para sa bawat pag-encode na sinusuri, makikita namin ang dalas ng kasalukuyang character at idinagdag ito sa "rating" ng pag-encode na ito. Ang pag-encode na may pinakamataas na rating ay malamang na ang text encoding.

$encodings = array("cp1251" => nangangailangan ng "specter_cp1251.php", "koi8r" => nangangailangan ng "specter_koi8r.php", "iso88595" => nangangailangan ng "specter_iso88595.php"); $enc_rates = array(); para sa ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)];
Huwag mo ring subukang patakbuhin ang code na ito sa iyong sarili - hindi ito gagana. Maaari mong isaalang-alang ang pseudocode na ito - Inalis ko ang mga detalye upang hindi makalat ang artikulo. Ang $char_specter ay eksaktong mga arrays na tinutukoy sa pastebin.

Mga resulta
Ang mga hilera ng talahanayan ay ang text encoding, ang mga column ay ang mga nilalaman ng $enc_rates array.

1) $str = "Tekstong Ruso";
0.441 | 0.020 | 0.085 | Windows-1251
0.049 | 0.441 | 0.166 | KOI8-R
0.133 | 0.092 | 0.441 | ISO-8859-5

Maayos ang lahat. Ang tunay na encoding ay mayroon nang 4 na beses na mas mataas na rating kaysa sa iba - ito ay para sa isang maikling teksto. Para sa mas mahabang mga teksto ang ratio ay magiging halos pareho.


cp1251 | koi8r | iso88595 |
0.013 | 0.705 | 0.331 | Windows-1251
0.649 | 0.013 | 0.201 | KOI8-R
0.007 | 0.392 | 0.013 | ISO-8859-5

Oops! Isang ganap na gulo. Iyon ay dahil ang malalaking letra sa CP1251 ay karaniwang tumutugma sa maliliit sa KOI8-R. At ang maliliit na titik, sa turn, ay ginagamit nang mas madalas kaysa sa mga malalaking titik. Kaya tinukoy namin ang caps string sa CP1251 bilang KOI8-R.
Subukan nating gawin itong case insensitively (“spectra” case insensitive)

1) $str = "Tekstong Ruso";
cp1251 | koi8r | iso88595 |
0.477 | 0.342 | 0.085 | Windows-1251
0.315 | 0.477 | 0.207 | KOI8-R
0.216 | 0.321 | 0.477 | ISO-8859-5

2) $str = "STRING CAPS RUSSIAN TEXT";
cp1251 | koi8r | iso88595 |
1.074 | 0.705 | 0.465 | Windows-1251
0.649 | 1.074 | 0.201 | KOI8-R
0.331 | 0.392 | 1.074 | ISO-8859-5

Gaya ng nakikita mo, ang tamang pag-encode ay patuloy na humahantong sa parehong case-sensitive na "mga spectrum" (kung ang linya ay naglalaman ng maliit na bilang ng malalaking titik) at may mga case-insensitive. Sa pangalawang kaso, sa mga case-insensitive, ang lead ay hindi masyadong kumpiyansa, siyempre, ngunit medyo matatag kahit sa maliliit na linya. Maaari mo ring paglaruan ang mga bigat ng mga titik - gawin silang nonlinear na may paggalang sa dalas, halimbawa.

5. Konklusyon

Ang paksa ay hindi sumasaklaw sa pagtatrabaho sa UTF-8 - walang pangunahing pagkakaiba dito, maliban na ang pagkuha ng mga code ng character at paghahati ng string sa mga character ay medyo mas mahaba/mas kumplikado.
Ang mga ideyang ito ay maaaring palawigin hindi lamang sa mga Cyrillic encoding, siyempre - ang tanong ay nasa "spectrums" lamang ng mga kaukulang wika/encoding.

P.S. Kung talagang kailangan/kawili-wili, pagkatapos ay ipo-post ko ang pangalawang bahagi ng isang ganap na gumaganang library sa GitHub. Bagaman naniniwala ako na ang data sa post ay sapat na upang mabilis na magsulat ng naturang library para sa iyong sariling mga pangangailangan - ang "spectrum" para sa wikang Ruso ay inilatag, madali itong mailipat sa lahat ng kinakailangang pag-encode.

May nakita akong problema - auto-detection ng page/text/whatever encoding. Ang gawain ay hindi na bago, at maraming mga bisikleta ang naimbento na. Ang artikulo ay naglalaman ng isang maikling pangkalahatang-ideya ng kung ano ang natagpuan sa Internet - kasama ang isang panukala ng kung ano sa tingin ko ay isang karapat-dapat na solusyon.

1. Bakit hindi mb_detect_encoding()?

Sa madaling salita, hindi ito gumagana.

Panoorin natin:
// Sa pasukan - Russian text na naka-encode CP1251 $string = iconv("UTF-8", "Windows-1251", "Lumapit siya kay Anna Pavlovna, hinalikan ang kamay nito, inilantad ang kanyang mabango at nagniningning na kalbong ulo sa kanya, at mahinahong umupo. pababa sa sofa."); // Tingnan natin kung ano ang ibinibigay sa atin ng md_detect_encoding(). Unang $strict = FALSE var_dump(mb_detect_encoding($string, array("UTF-8"))); // UTF-8 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"))); // Windows-1251 var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"))); // KOI8-R var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"))); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"))); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"))); // ISO-8859-5 // Now $strict = TRUE var_dump(mb_detect_encoding($string, array("UTF-8"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"), TRUE)); // FALSE var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"), TRUE)); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"), TRUE)); // ISO-8859-5
Tulad ng nakikita mo, ang output ay isang kumpletong gulo. Ano ang gagawin natin kapag hindi malinaw kung bakit ganito ang pagkilos ng isang function? Tama, i-Google natin. Nakakita ako ng magandang sagot.

Upang tuluyang maalis ang lahat ng pag-asa sa paggamit ng mb_detect_encoding(), kailangan mong tingnan ang source code ng extension ng mbstring. Kaya, isara ang iyong mga manggas at umalis tayo:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // line 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + click:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:643 const char* mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( const mbfl_encoding *encoding; encoding = mbfl,listz_encoding , mahigpit);
Ctrl + click:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * kilalanin ang encoding */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Hindi ko ipo-post ang buong teksto ng pamamaraan upang hindi kalat ang artikulo sa mga hindi kinakailangang mapagkukunan. Ang mga interesado ay magkakaroon ng hitsura para sa kanilang sarili. Interesado kami sa numero ng linya 593, kung saan aktwal naming tinitingnan kung tumutugma ang character sa pag-encode:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_function)(*p, filter); if (filter->flag) ( masama++; )
Narito ang mga pangunahing filter para sa single-byte Cyrillic:

Windows-1251 (napanatili ang mga orihinal na komento)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* ang pangit ng lahat ng ito ngayon! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filter) ( kung (c >= 0x80 && c< 0xff) filter->bandila = 0;

ibang filter->
KOI8-R< 0xff) filter->// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filter) ( kung (c >= 0x80 && c

bandila = 0;
iba pang filter->bandila = 1; /* hindi ito */ bumalik c; )
ISO-8859-5 (lahat ay masaya dito)

// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter) ( return c; )

Tulad ng nakikita mo, ang ISO-8859-5 ay palaging nagbabalik ng TRUE (upang ibalik ang FALSE, kailangan mong itakda ang filter->flag = 1).

Kapag tiningnan namin ang mga filter, ang lahat ay nahulog sa lugar. Walang paraan upang makilala ang CP1251 mula sa KOI8-R. Sa pangkalahatan, ang ISO-8859-5, kung ito ay nasa listahan ng mga pag-encode, ay palaging makikita bilang tama.

Sa pangkalahatan, mabibigo. Naiintindihan ito - sa pangkalahatan, imposibleng malaman ang pag-encode sa pamamagitan lamang ng mga code ng character, dahil ang mga code na ito ay nagsalubong sa iba't ibang mga pag-encode.

2. Ano ang dinadala ng Google
At inilalabas ng Google ang lahat ng uri ng kapahamakan. Hindi ko ipo-post ang pinagmulan dito, tingnan mo ang iyong sarili kung gusto mo (alisin ang puwang pagkatapos ng http://, hindi ko alam kung paano ipakita ang teksto nang walang link):

Http://deer.org.ua/2009/10/06/1/

1) muli ang mga code ng character:

2) sa aking opinyon, isang napaka-kagiliw-giliw na solusyon:
Mga kalamangan at kahinaan sa komento sa link. Sa personal, sa palagay ko ang solusyon na ito ay kalabisan lamang para sa pag-detect ng pag-encode - lumalabas na napakalakas nito. Ang pagtukoy sa pag-encode dito ay isang side effect).

4. Actually, ang desisyon ko

Ang ideya ay lumitaw habang tinitingnan ang pangalawang link mula sa nakaraang seksyon. Ang ideya ay ang mga sumusunod: kumukuha kami ng isang malaking Russian text, sinusukat ang mga frequency ng iba't ibang mga titik, at ginagamit ang mga frequency na ito upang makita ang pag-encode. Sa hinaharap, sasabihin ko kaagad na magkakaroon ng mga problema sa malalaki at maliliit na titik. Samakatuwid, nagpo-post ako ng mga halimbawa ng mga frequency ng titik (tawagin natin itong "spectrum"), parehong case-sensitive at case-insensitive (sa pangalawang kaso, nagdagdag ako ng mas malaki sa isang maliit na titik na may parehong frequency, at inalis lahat ang mas malaki). Sa mga "spectra" na ito ang lahat ng mga titik na may mga frequency na mas mababa sa 0.001 at isang puwang ay pinutol. Ito ang nakuha ko pagkatapos iproseso ang "Digmaan at Kapayapaan":

Case-sensitive na "spectrum":
array ("o" => 0.095249209893009, "e" => 0.06836817536026, "a" => 0.067481298384992, "i" => 0.055995027400041, "n" => 2 .002252892226507, "N " => 0.0021318391371162, "P" => 0.0018574762967903, "f" => 0.0015961610948418, "B" => 0.0014044332975731, "A9" => 30. 0.0012623590130186, "K" => 0.0011804488387602, "M" => 0.001061932790165,)

Case insensitive:
array ("O" => 0.095249209893009, "o" => 0.095249209893009, "E" => 0.06836817536026, "e" => 0.06836817536026, "A" => 8.06, "A" => 8.026, "A" 67481298384992, "AT" => 0.055995027400041 , "i" => 0.055995027400041, .... "C" => 0.0029893589260344, "c" => 0.0029893589260344, "sch" => 0.00246491635014 => 6.00246491635014 "E" => 0.002252892226507, "e " => 0.002252892226507, "F" => 0.0015961610948418, "f" => 0.0015961610948418,)

Spectra sa iba't ibang pag-encode (ang mga array key ay ang mga code ng kaukulang mga character sa naaangkop na pag-encode):

Susunod. Kumuha kami ng teksto ng hindi kilalang pag-encode, para sa bawat pag-encode na sinusuri, makikita namin ang dalas ng kasalukuyang character at idinagdag ito sa "rating" ng pag-encode na ito. Ang pag-encode na may pinakamataas na rating ay malamang na ang text encoding.

$encodings = array("cp1251" => nangangailangan ng "specter_cp1251.php", "koi8r" => nangangailangan ng "specter_koi8r.php", "iso88595" => nangangailangan ng "specter_iso88595.php"); $enc_rates = array(); para sa ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)];
Huwag mo ring subukang patakbuhin ang code na ito sa iyong sarili - hindi ito gagana. Maaari mong isaalang-alang ang pseudocode na ito - Inalis ko ang mga detalye upang hindi makalat ang artikulo. Ang $char_specter ay eksaktong mga arrays na tinutukoy sa pastebin.

Mga resulta
Ang mga hilera ng talahanayan ay ang text encoding, ang mga column ay ang mga nilalaman ng $enc_rates array.

1) $str = "Tekstong Ruso";
0.441 | 0.020 | 0.085 | Windows-1251
0.049 | 0.441 | 0.166 | KOI8-R
0.133 | 0.092 | 0.441 | ISO-8859-5

Maayos ang lahat. Ang tunay na encoding ay mayroon nang 4 na beses na mas mataas na rating kaysa sa iba - ito ay para sa isang maikling teksto. Para sa mas mahabang mga teksto ang ratio ay magiging halos pareho.


cp1251 | koi8r | iso88595 |
0.013 | 0.705 | 0.331 | Windows-1251
0.649 | 0.013 | 0.201 | KOI8-R
0.007 | 0.392 | 0.013 | ISO-8859-5

Oops! Isang ganap na gulo. Iyon ay dahil ang malalaking letra sa CP1251 ay karaniwang tumutugma sa maliliit sa KOI8-R. At ang maliliit na titik, sa turn, ay ginagamit nang mas madalas kaysa sa mga malalaking titik. Kaya tinukoy namin ang caps string sa CP1251 bilang KOI8-R.
Subukan nating gawin itong case insensitively (“spectra” case insensitive)

1) $str = "Tekstong Ruso";
cp1251 | koi8r | iso88595 |
0.477 | 0.342 | 0.085 | Windows-1251
0.315 | 0.477 | 0.207 | KOI8-R
0.216 | 0.321 | 0.477 | ISO-8859-5

2) $str = "STRING CAPS RUSSIAN TEXT";
cp1251 | koi8r | iso88595 |
1.074 | 0.705 | 0.465 | Windows-1251
0.649 | 1.074 | 0.201 | KOI8-R
0.331 | 0.392 | 1.074 | ISO-8859-5

Gaya ng nakikita mo, ang tamang pag-encode ay patuloy na humahantong sa parehong case-sensitive na "mga spectrum" (kung ang linya ay naglalaman ng maliit na bilang ng malalaking titik) at may mga case-insensitive. Sa pangalawang kaso, sa mga case-insensitive, ang lead ay hindi masyadong kumpiyansa, siyempre, ngunit medyo matatag kahit sa maliliit na linya. Maaari mo ring paglaruan ang mga bigat ng mga titik - gawin silang nonlinear na may paggalang sa dalas, halimbawa.

5. Konklusyon

Ang paksa ay hindi sumasaklaw sa pagtatrabaho sa UTF-8 - walang pangunahing pagkakaiba dito, maliban na ang pagkuha ng mga code ng character at paghahati ng string sa mga character ay medyo mas mahaba/mas kumplikado.
Ang mga ideyang ito ay maaaring palawigin hindi lamang sa mga Cyrillic encoding, siyempre - ang tanong ay nasa "spectrums" lamang ng mga kaukulang wika/encoding.

P.S. Kung talagang kailangan/kawili-wili, pagkatapos ay ipo-post ko ang pangalawang bahagi ng isang ganap na gumaganang library sa GitHub. Bagaman naniniwala ako na ang data sa post ay sapat na upang mabilis na magsulat ng naturang library para sa iyong sariling mga pangangailangan - ang "spectrum" para sa wikang Ruso ay inilatag, madali itong mailipat sa lahat ng kinakailangang pag-encode.

Ideya - Lottery

Hindi ako nakaisip ng ideya ng pagkuha ng pag-encode, ngunit sa kasamaang-palad, hindi ko masasabi sa iyo ang may-akda ngayon, dahil ito ay mga 4 na taon na ang nakakaraan at kung saan ko nakuha ang impormasyong ito ay matagal nang nakalimutan. Ang may-akda ay nagmungkahi ng isang kahulugan at nagpakita ng isang halimbawa para sa 1-2 na pag-encode sa Python. Ang pagiging simple ng kanyang solusyon ay hindi ako iniwan sa isang tabi, at binuo ko ito sa nais na resulta.
Ang kakanyahan ng ideya ay nasa mismong mga encoding code table. Tulad ng alam mo, ang anumang pag-encode ay naglalaman ng sarili nitong talahanayan ng code at ang bawat karakter sa pag-encode ay itinalaga ng isang partikular na halaga. Hindi ako magpapakita ng mga talahanayan ng pag-encode dito; ngayon ay medyo madali na silang mahanap sa Internet.
Ang prinsipyo ng pagpapatupad ay ang mga sumusunod:
  1. Ang isang array variable ay nilikha upang iimbak ang resulta ng "pagsusuri" ng na-verify na teksto. Ang bawat elemento ng array ay maglalaman ng resulta para sa isang partikular na encoding.
  2. Ang text na natanggap bilang input sa function ay simbolikong inuulit.
  3. Ang ordinal (ang kahulugan ng karakter na iyon) ay kinuha mula sa bawat karakter at inihambing sa hanay ng pag-encode.
  4. Kung ang value ay bumaba sa isang uppercase (capital) na character, ang value ng 1 ay idaragdag sa array element na nag-iimbak ng resulta ng encoding na ito.
  5. Kung ang value ay bumaba sa isang lowercase (maliit) na character, ang value ng 3 ay idaragdag sa array element na nag-iimbak ng resulta ng encoding na ito.
  6. Ang pag-encode na iyon, o mas tiyak, ang elemento ng array na nag-iimbak ng resulta ng pag-encode nito, na nakakuha ng pinakamaraming puntos, ay malamang na ang orihinal na pag-encode.
Wasto ang algorithm na ito para sa mga single-byte na encoding gaya ng KOI-8, CP1251 (windows-1251) at iba pa. Gayunpaman, para sa mga double-byte na pag-encode (UTF-8 sa aking kaso), ang diskarte na ito ay magbubunga ng isang maling resulta. Upang magsimula, sinubukan kong lutasin ang isyung ito sa pamamagitan ng pagdaragdag ng 5 para sa mga malalaking titik at 7 para sa maliliit na mga character Ang resulta ay naging mas mahusay, ngunit naroroon pa rin ang mga error sa pagkilala. Pagkatapos ng ilang eksperimento, napagpasyahan ko na upang matukoy nang tama ang UTF, para sa mga malalaking titik, 10 ay dapat idagdag sa resulta, para sa mga maliliit na character, 14, iyon ay, 2 beses na higit pa kaysa sa aking unang hula. Gayunpaman, para sa isang mas mahusay na visual na pag-unawa sa code, nag-iwan ako ng 5 at 7 para sa mga character ng UTF, ayon sa pagkakabanggit, at sa panahon ng pagsubok, nadagdagan ko ang mga halagang ito ng 2 at idinagdag ang mga ito sa resulta.
Iyon talaga ang buong algorithm. At nang walang anumang hindi kinakailangang abala.
Karamihan sa mga oras na ginugol ko sa pagpapatupad ng function na ito ay, siyempre, naghahanap ng mga talahanayan ng code at ang tamang pag-aayos ng mga saklaw. Hindi lamang ito medyo mahirap noong una kong isinulat ang function na ito, medyo mahirap hanapin ang kasalukuyang code table, ngunit pati na rin ang mga hanay ng mga character sa mga ito ay tumalon nang random. Gayunpaman, pagkatapos ay nanirahan ako sa pinakabagong (at hanggang ngayon) na pag-encode: UTF-8, CP1251, KOI8-R, IBM866, ISO-8859-5 at MAC. Kung ang mga pag-encode na ito ay hindi sapat para sa iyo, maaari mong dagdagan ang code batay sa algorithm na ito.

Mula sa mga salita hanggang sa pagsasanay

Sa totoo lang, ang buong code ng function sa Python ay ganito ang hitsura:

Mga Encoding = ( "UTF-8": "utf-8", "CP1251": "windows-1251", "KOI8-R": "koi8-r", "IBM866": "ibm866", "ISO-8859- 5": "iso-8859-5", "MAC": "mac", ) """ Pagtukoy sa text encoding """ def get_codepage(str = Wala): uppercase = 1 lowercase = 3 utfupper = 5 utflower = 7 codepages = () para sa enc sa encodings.keys(): codepages = 0 kung str ay hindi Wala at len(str) > 0: last_simb = 0 para sa simb sa str: simb_ord = ord(simb) """non-Russian character " "" kung simb_ord< 128 or simb_ord >256: ipagpatuloy ang """UTF-8""" kung last_simb == 208 at (143< simb_ord < 176 or simb_ord == 129): codepages["UTF-8"] += (utfupper * 2) if (last_simb == 208 and (simb_ord == 145 or 175 < simb_ord < 192)) \ or (last_simb == 209 and (127 < simb_ord < 144)): codepages["UTF-8"] += (utflower * 2) """CP1251""" if 223 < simb_ord < 256 or simb_ord == 184: codepages["CP1251"] += lowercase if 191 < simb_ord < 224 or simb_ord == 168: codepages["CP1251"] += uppercase """KOI8-R""" if 191 < simb_ord < 224 or simb_ord == 163: codepages["KOI8-R"] += lowercase if 222 < simb_ord < 256 or simb_ord == 179: codepages["KOI8-R"] += uppercase """IBM866""" if 159 < simb_ord < 176 or 223 < simb_ord < 241: codepages["IBM866"] += lowercase if 127 < simb_ord < 160 or simb_ord == 241: codepages["IBM866"] += uppercase """ISO-8859-5""" if 207 < simb_ord < 240 or simb_ord == 161: codepages["ISO-8859-5"] += lowercase if 175 < simb_ord < 208 or simb_ord == 241: codepages["ISO-8859-5"] += uppercase """MAC""" if 221 < simb_ord < 255: codepages["MAC"] += lowercase if 127 < simb_ord < 160: codepages["MAC"] += uppercase last_simb = simb_ord idx = "" max = 0 for item in codepages: if codepages >max: max = codepages idx = item return idx
Halimbawa ng function na tawag

Mag-print ng mga encoding

Paano ang tungkol sa PHP?

Ang muling pagsulat ng isang handa na function mula sa Python patungo sa PHP ay hindi mahirap. Sa hitsura, halos hindi ito naiiba sa magulang nito sa Python:

/** * Tukuyin ang text encoding * @param String $text Text * @return String Text encoding */ function get_codepage($text = "") ( kung (!empty ($text)) ($utflower = 7; $utfupper = 5; $maliit na titik = 3; $uppercase = 1; $huling_simb = 0; " => 0, "ISO-8859-5" => 0, "MAC" => 0,); para sa ($a = 0; $a< strlen($text); $a++) { $char = ord($text[$a]); // non-russian characters if ($char<128 || $char>256) magpatuloy;<176) || $char==129)) $charsets["UTF-8"] += ($utfupper * 2); if ((($last_simb==208) && (($char>// UTF-8 kung ($($last_simb==208) && ($char>143 && $char<192) || $char==145)) || ($last_simb==209 && $char>175 && $char<144)) $charsets["UTF-8"] += ($utflower * 2); // CP1251 if (($char>127 && $char<256) || $char==184) $charsets["CP1251"] += $lowercase; if (($char>223 && $char<224) || $char==168) $charsets["CP1251"] += $uppercase; // KOI8-R if (($char>223 && $char<224) || $char==163) $charsets["KOI8-R"] += $lowercase; if (($char>191 && $char<256) || $char==179) $charsets["KOI8-R"] += $uppercase; // IBM866 if (($char>222 && $char<176) || ($char>127 && $char<241)) $charsets["IBM866"] += $lowercase; if (($char>175 && $char<160) || $char==241) $charsets["IBM866"] += $uppercase; // ISO-8859-5 if (($char>159 && $char<240) || $char==161) $charsets["ISO-8859-5"] += $lowercase; if (($char>// UTF-8 kung ($($last_simb==208) && ($char>143 && $char<208) || $char==241) $charsets["ISO-8859-5"] += $uppercase; // MAC if ($char>207 && $char<255) $charsets["MAC"] += $lowercase; if ($char>175 && $char<160) $charsets["MAC"] += $uppercase; $last_simb = $char; } arsort($charsets); return key($charsets); } }
Halimbawa ng function na tawag

221 && $char

Echo get_codepage(file_get_contents("test.txt"));

Hindi mo dapat subukang i-crash test ang function na ito. Malinaw mula sa algorithm na ang mas kaunting text na natatanggap nito bilang input, mas malaki ang posibilidad na makikilala ng function ang pag-encode nang hindi tama. Sa kabilang banda, ang pagpapakain ng mga volume ng Leo Tolstoy ay walang saysay din: ang pamamaraang ito ay mahusay na nakayanan ang isang maliit na pangungusap na 100-200 na mga character. At kahit na sa mga halimbawa ng tawag sa input ipinadala ko ang buong nilalaman ng isang tiyak na file na "test.txt", na dapat ay naglalaman ng teksto na ang pag-encode ay kailangang matukoy, ang isang maliit na seksyon ng teksto ay maaaring (at dapat) ipinasa sa input ng function.
Isinasaalang-alang ko ang mga perversion na may magkahalong uppercase at lowercase na mga titik sa pangkalahatan ay hindi angkop sa kasong ito, dahil ang paraang ito ay isinulat para sa isang ordinaryong, run-of-the-mill na gawain na may humigit-kumulang na marunong magbasa ng Ruso. At ang ganitong mga eksperimento ay madalas na nagpapaalala sa akin ng isang biro:

Ang isang planta ng pagproseso ng kahoy sa Russia ay nakakuha ng isang yunit ng Hapon. Ang mga manggagawang Ruso ay nagtipon sa paligid niya at alamin natin kung paano siya nagtatrabaho. Kinuha ng isa ang board at idinikit ito. Unit:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz... At the exit is a finished stool. Guys: Wow!!! Unit na naka-display: well, ano sa tingin mo? Ang isa pa ay kumuha ng hindi pa natatabas na log at ipinasok ito sa unit. Unit: Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzng ... ang output ay isang tapos na inukit sideboard. Guys: Wow!!! Unit na naka-display: well, ano sa tingin mo? Hindi nakatiis ang pangatlong lalaki, hinila niya ang isang riles mula sa kung saan at idinikit ito sa unit. Yunit: drrrrrrr-tyh-tyh-tyh... Nagsimula itong umusok at ang nakalagay sa display ay: Wow!!! Guys: eh ano sa tingin mo!!!
Kaya't para sa gayong mga baluktot na pagsubok ay malamang na kailangan mo ng isang baluktot na algorithm, na hindi ang function na ito. At mula sa pagsasanay sasabihin ko na sa panahon ng aking paggamit sa loob ng 4 na taon, ang pamamaraang ito ay hindi kailanman nagpabaya sa akin at palaging nagbibigay ng tamang resulta.
Umaasa ako na ang aking artikulo ay magiging kapaki-pakinabang sa isang tao.
Salamat sa iyong pansin.

Kapag ginagamit ang lahat o bahagi ng nilalaman, huwag kalimutang magbigay ng isang link sa pinagmulan, iyon ay, sa aking blog.

Ang isang problema ay lumitaw: kung paano mabilis na matukoy ang pag-encode ng isang text string na may kaugnayan sa UTF-8.

Nasa ibaba ang isang function upang suriin kung ang UNICODE (UTF-8) encoding ay kailangang i-convert sa WINDOWS (win-1251) encoding

Ang function ay nagbibigay ng isang medyo tumpak na sagot, kahit na ito ay hindi batay sa character-by-code conversion.

function detect_my_utf($s)( $s=urlencode($s); // sa ilang kaso - isang hindi kinakailangang operasyon (comment out) $res="0"; $j=strlen($s); $s2=strtoupper($ s); $s2=str_replace("%D0","",$s2); $k; kung ($m>1.2)&&($m

Maikling paglalarawan ng pag-andar detect_my_utf():

  • convert (string sa espesyal na format)
  • kalkulahin ang haba ng papasok na string
  • i-capitalize ang lahat ng letra ng string
  • alisin ang mga partikular na code %D0 at %D1
  • kalkulahin ang haba ng bagong linya
  • nakukuha namin ang ratio ng lumang linya sa bago

Kung ang ratio na ito ay 1 o malapit dito, pinaghihinalaan na ang papasok na string ay hindi naka-encode sa UNICODE. Kung ang ratio na ito ay nasa hanay mula 1.2 hanggang 2.2, maaari mong ligtas na i-recode ang string sa WINDOWS win-1251 encoding.

Ang output ng function ay 0 o 1, ayon sa pagkakabanggit, hindi UNICODE o UNICODE.

Mga halimbawa ng pagsasagawa ng function:

Papasok na string: РїР?С?С?Р?Р?Рє С?Р?Р·Р?Р°Р?РёС? Р°Р?РёР?Р°С+РёРё Р? imageready Na-convert na string: %D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BE%D0%BA %D1%81%D0%BE%D0%B7%D0%B4%D0 %B0%D0%BD%D0%B8%D1%8F %D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%86%D0%B8%D0%B8%20%D0 %B2 imageready Resulta ng function: 1 Naka-encode na parirala: pagkakasunud-sunod ng paglikha ng animation sa imageready

Papasok na string: R?S?R?R?R?S

Papasok na string: РїС?Р?Р?С?Р°Р?Р?Р° С+їРчР?РёС?

Input string: gabay sa pagguhit Na-convert na string: %EF%EE%F1%EE%E1%E8%E5 %EF%EE %F0%E8%F1%EE%E2%E0%ED%E8%FE Resulta ng function: 0 Na-encode na parirala : gabay sa pagguhit Ang algorithm na ito ay mahusay na nakayanan ang iba't ibang mga papasok na string bilang bahagi ng serbisyo ng istatistika ng conversion ng search engine.

Mga kagiliw-giliw na materyales sa site:

  • Isang artikulo tungkol sa interes ng search engine ng site. Marahil ang ilan sa mga materyales ay hindi na napapanahon pagkatapos ng 10 taon, ngunit ang ilang mga punto ay nagkakahalaga ng pagbibigay pansin.

  • Ang iyong pananaw sa problema ng pagpapalitan ng mga hyperlink sa pagitan ng isang donor site at mga site ng tatanggap.

  • Isa pang life hack. Tinalo namin ang mga hindi tapat na manlalaro sa larong "Balda". Isang malaking database ng mga salita na madaling mapalawak.

Nagbasa ako ng maraming mga teksto mula sa iba't ibang mga RSS feed at inilagay ang mga ito sa aking database.

Siyempre, may ilang magkakaibang pag-encode ng character na ginagamit sa mga tubo, hal. UTF-8 at ISO-8859-1.

Sa kasamaang palad, kung minsan ay may mga problema na lumitaw sa mga pag-encode ng teksto. Halimbawa:

1) Ang "ß" sa "Fußball" ay dapat magmukhang ganito sa aking database: "Ÿ". Kung ito ay "Ÿ", ito ay ipinapakita nang tama.

2) Minsan ang "ß" sa "Fußball" ay ganito sa aking database: "ß". Pagkatapos ito ay ipinapakita nang hindi tama, siyempre.

3) Sa ibang mga kaso, ang "ß" ay iniimbak bilang "ß" - samakatuwid ay walang anumang pagbabago. Pagkatapos ay hindi rin ito ipinapakita nang tama.

Ano ang maaari kong gawin upang maiwasan ang mga kaso 2 at 3?

Paano ko gagawin ang lahat ng parehong pag-encode, mas mabuti ang UTF-8? Kailan ko dapat gamitin ang utf8_encode(), kailan ko dapat gamitin ang utf8_decode() (malinaw kung ano ang epekto, ngunit kailan ako dapat gumamit ng mga function?), at kailan ko dapat gawin ang anumang bagay sa input?

Maaari mo ba akong tulungan at sabihin sa akin kung paano gawin ang lahat ng parehong coding? Marahil sa mb-detect-encoding() function? Maaari ba akong magsulat ng isang function para dito? Kaya ang aking mga problema ay: 1) Paano malalaman kung anong pag-encode ang ginagamit sa teksto 2) Paano ito i-convert sa UTF-8 - anuman ang lumang pag-encode

EDIT: Gagana ba ang feature na ito?

Function correct_encoding ($text) ($current_encoding = mb_detect_encoding ($text, "auto"); $text = iconv($current_encoding, "UTF-8", $text); ibalik ang $text; )

Sinubukan ko ito ngunit hindi ito gumana. Anong meron sa kanya?

24 na sagot

Kung ilalapat mo ang utf8_encode() sa isang umiiral nang string ng UTF8, ibabalik nito ang magulo na output ng UTF8.

Gumawa ako ng isang function na lumulutas sa lahat ng mga problemang ito. Ito ay tinatawag na Encoding::toUTF8().

Hindi mo kailangang malaman kung ano ang pag-encode ng iyong mga string. Ito ay maaaring Latin1 (iso 8859-1), Windows-1252 o UTF8, o ang string ay maaaring naglalaman ng mga ito. Kino-convert ng Encoding::toUTF8() ang lahat sa UTF8.

Ginawa ko ito dahil binibigyan ako ng serbisyo ng stream ng data, lahat ay nagulo, pinaghahalo ang UTF8 at Latin1 sa isang linya.

Paggamit:

Require_once("Encoding.php"); gamitin ang \ForceUTF8\Encoding; // Namespaced na ngayon. $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

Nagsama ako ng isa pang function, Encoding::fixUFT8(), na mag-aayos sa bawat string ng UTF8 na mukhang magulo.

Paggamit:

Require_once("Encoding.php"); gamitin ang \ForceUTF8\Encoding; // Namespaced na ito ngayon. $utf8_string = Encoding::fixUTF8($garbled_utf8_string);

Echo Encoding::fixUTF8("Fédération Camerounaise de Football"); echo Encoding::fixUTF8("Fédération Camerounaise de Football"); echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football"); echo Encoding::fixUTF8("Fédération Camerounaise de Football");

Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football

Update: Na-convert ko ang function (forceUTF8) sa isang pamilya ng mga static na function sa Encoding class. Bagong function - Encoding::toUTF8().

Una kailangan mong matukoy kung anong encoding ang ginamit. Dahil nag-parse ka ng mga RSS feed (posible sa HTTP), dapat mong basahin ang pag-encode mula sa charset parameter ng Content-Type na field ng HTTP header. Kung nawawala ito, basahin ang pag-encode mula sa katangian ng pag-encode ng pagtuturo sa pagproseso. Kung nawawala rin ito, gamitin ang UTF-8 gaya ng tinukoy sa spec.

Baguhin Narito ang malamang na gagawin ko:

Ang pagtukoy sa pag-encode ay mahirap.

Gumagana ang mb_detect_encoding sa pamamagitan ng paghula batay sa maraming kandidatong ipinapasa mo. Sa ilang mga pag-encode, hindi wasto ang ilang mga byte na pagkakasunud-sunod, kaya maaari itong makilala sa pagitan ng iba't ibang mga kandidato. Sa kasamaang palad, mayroong maraming mga pag-encode kung saan ang parehong mga byte ay wasto (ngunit naiiba). Sa mga kasong ito, imposibleng matukoy ang pag-encode; Maaari mong ipatupad ang iyong sariling lohika upang makagawa ng mga hula sa mga kasong ito. Halimbawa, ang data na nagmumula sa isang Japanese site ay malamang na nasa Japanese encoding.

Habang nakikipag-usap ka lang sa mga wikang Western European, tingnan natin ang tatlong pangunahing pag-encode: utf-8, iso-8859-1 at cp-1252. Dahil ito ang mga default na halaga para sa maraming platform, malamang na mali rin ang pag-uulat ng mga ito. Halimbawa. kung ang mga tao ay gumagamit ng iba't ibang mga pag-encode, malamang na magiging bukas sila tungkol dito, dahil kung hindi, ang kanilang software ay madalas na masira. Kaya isang magandang diskarte ang magtiwala sa provider maliban kung ang pag-encode ay idineklara bilang isa sa tatlong ito. Dapat mo pa ring doblehin na ito ay aktwal na wasto gamit ang mb_check_encoding (tandaan na ang balido ay hindi katulad nito - ang parehong input ay maaaring maging wasto para sa maraming pag-encode). Kung isa ito sa mga ito, maaari mong gamitin ang mb_detect_encoding upang matukoy ang pagkakaiba sa pagitan nila. Sa kabutihang palad, ito ay medyo deterministiko; Kailangan mo lang gamitin ang tamang pagkakasunud-sunod ng pagtuklas, na UTF-8,ISO-8859-1,WINDOWS-1252.

Sa sandaling natuklasan mo ang pag-encode, kailangan mong i-convert ito sa panloob na representasyon (ang utf-8 ay ang tanging makatwirang pagpipilian). Kino-convert ng utf8_encode function ang iso-8859-1 sa utf-8 kaya magagamit lang ito para sa partikular na uri ng input na iyon. Para sa iba pang pag-encode, gamitin ang mb_convert_encoding.

Ang cheat sheet na ito ay naglilista ng ilang karaniwang caveat na nauugnay sa paghawak ng UTF-8 sa PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Ang function na ito, na nakakakita ng mga multibyte na character sa isang string, ay maaari ding maging kapaki-pakinabang ():

Function detectUTF8($string) ( return preg_match("%(?: [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte |\xE0[\xA0-\xBF][\x80- \xBF] # hindi kasama ang mga overlong |[\xE1-\xEC\xEE\xEF][\x80-\xBF](2) # straight 3-byte |\xED[\x80-\x9F][\x80-\xBF] # hindi kasama ang mga kahalili |\xF0[\x90-\xBF][\x80-\xBF](2) # eroplano 1-3 |[\xF1-\xF3][\x80-\xBF](3) # eroplano 4- 15 |\xF4[\x80-\x8F][\x80-\xBF](2) # eroplano 16)+%xs", $string); )

Medyo paalala, sinabi mo na ang "ß" ay dapat lumabas bilang "Ÿ" sa iyong database.

Ito ay marahil dahil sa ang katunayan na ikaw ay gumagamit ng isang database na may latin1 character encoding o marahil ang php-mysql na koneksyon ay hindi na-configure nang tama, ipinapalagay ng php na ang iyong mysql ay na-configure upang gamitin ang utf-8 kaya ito ay nagpapadala ng data bilang utf8 ngunit ang iyong Naniniwala ang mysql na ang php ay nagpapadala ng data na naka-encode bilang iso-8859-1, kaya maaari nitong subukang i-encode muli ang iyong ipinadalang data bilang utf-8, na nagdudulot ng mga problemang tulad nito.

Tingnan mo ito, baka makatulong sa iyo: http://php.net/manual/en/function.mysql-set-charset.php

Kailangan mong suriin ang pag-encode sa input dahil ang mga tugon ay maaaring ma-encode ng iba't ibang mga pag-encode.
Pinipilit kong ipadala ang lahat ng nilalaman sa UTF-8 sa pamamagitan ng pagtukoy at pagsasalin gamit ang sumusunod na function:

Function fixRequestCharset() ($ref = array(&$_GET, &$_POST, &$_REQUEST); foreach ($ref as &$var) (foreach ($var as $key => $val) ($encoding = mb_detect_encoding ($var[ $key ], mb_detect_order(), true); if (!$encoding) continue; UTF-8", $var[ $key ]); kung magpapatuloy ang ($encoding === false); $var[ $key ] = $encoding; ) ) ) )

Iko-convert ng pamamaraang ito ang lahat ng PHP variable na nagmumula sa remote host sa UTF-8.
O huwag pansinin ang halaga kung hindi matukoy o ma-convert ang pag-encode.
Maaari mo itong i-customize ayon sa iyong mga pangangailangan.
Tawagan lang ito bago gumamit ng mga variable.

Ang iyong pag-encode ay mukhang naka-encode ka sa UTF-8 dalawang beses; iyon ay, mula sa ilang iba pang pag-encode, sa UTF-8 at muli sa UTF-8. Para bang na-convert mo ang iso-8859-1 mula sa iso-8859-1 patungong utf-8 at itinuring na may bagong linya bilang iso-8859-1 para sa isa pang conversion sa UTF-8.

Narito ang ilang pseudocode para sa iyong ginawa:

$inputstring = getFromUser(); $utf8string = iconv($current_encoding, "utf-8", $inputstring); $flawedstring = iconv($current_encoding, "utf-8", $utf8string);

Dapat mong subukan:

  • tuklasin ang pag-encode gamit ang mb_detect_encoding() o anumang gusto mong gamitin
  • kung UTF-8, i-convert sa iso-8859-1 at ulitin ang hakbang 1
  • sa wakas ay i-convert pabalik sa UTF-8

Ipinapalagay na sa "average" na conversion ay gumamit ka ng iso-8859-1. Kung gumamit ka ng windows-1252, pagkatapos ay i-convert sa windows-1252 (latin1). Ang orihinal na source encoding ay hindi mahalaga; ang ginamit mo sa mali, pangalawang conversion.

Ito ang aking hula kung ano ang nangyari; maaari kang gumawa ng kaunti pa upang makakuha ng apat na byte sa halip na isang pinalawig na ASCII byte.

Gumagamit din ang German ng iso-8859-2 at windows-1250 (latin2).

Ang pagdidisenyo ng pag-encode ng character para sa mga RSS feed ay mukhang kumplikado. Kahit na ang mga regular na web page ay madalas na nagtatanggal o nagsisinungaling tungkol sa kanilang pag-encode.

Kaya, maaari mong subukang gamitin ang tamang paraan upang makita ang pag-encode, at pagkatapos ay bumalik sa ilang paraan ng awtomatikong pagtuklas (paghula).

Alam kong ito ay isang lumang tanong, ngunit naniniwala ako na ang isang kapaki-pakinabang na sagot ay hindi kailanman masakit. Nagkakaroon ako ng mga problema sa aking pag-encode sa pagitan ng mga desktop application, SQLite at GET/POST na mga variable. Ang ilan sa kanila ay nasa UTF-8, ang ilan sa kanila ay nasa ASCII, at kadalasan ay nakakalito ang mga bagay kapag may kasamang mga dayuhang karakter.

Narito ang aking solusyon. Pinapatag nito ang iyong GET/POST/REQUEST (Iniwan ko ang cookies, ngunit maaari mong idagdag ang mga ito kung kinakailangan) sa bawat pag-load ng pahina bago iproseso. Gumagana ito nang maayos sa header. Magbibigay ng mga babala ang PHP kung hindi nito awtomatikong matukoy ang source encoding, kaya pinipigilan ang mga babalang ito gamit ang @.

//I-convert ang lahat sa aming mga vars sa UTF-8 para sa mahusay na paglalaro sa database... //Gumamit ng ilang auto detection dito para tulungan kaming hindi magdoble-encode... //Sugpuin ang mga posibleng babala gamit ang @ kapag hindi matukoy ang pag-encode subukan ($process = array(&$_GET, &$_POST, &$_REQUEST); while (list($key, $val) = each($process)) ( foreach ($val as $k => $v) ( unset ($process[$key][$k]); if (is_array($v)) ($process[$key][@mb_convert_encoding($k,"UTF-8","auto")] = $ v; $process = &$process[$key][@mb_convert_encoding($k,"UTF-8","auto")]; ","auto")] = @mb_convert_encoding($v,"UTF-8","auto"); ) ) ) unset($process); ) catch(Exception $ex)()

Sinusuri ko ang mga solusyon sa coding gamit ang AGES at ang page na ito ay marahil ang katapusan ng mga taon ng paghahanap! Sinuri ko ang ilan sa mga mungkahi na iyong binanggit at narito ang aking mga tala:

Ito ang linya ng pagsubok ko:

ito ang linyang "wròng wrìtten" na hindi ko ginamit para espesyal na i-configure ang mga chàrs para makita ang mga ito, na-convert sa pamamagitan ng fùnctìon!! at ano ito!

Ang font ng page ko ay UTF-8

Kung gagawin ko ang INSERT sa ganitong paraan, mayroon akong ilang mga character sa aking DB na malamang na nanggaling sa Mars... kaya kailangan kong i-convert ang mga ito sa "matino" na UTF-8. Sinubukan ko ang utf8_encode() ngunit ang mga alien na character ay lumusob pa rin sa aking database...

Kaya, sinubukan kong gamitin ang function na forceUTF8 na matatagpuan sa numero 8, ngunit sa DB ang naka-save na string ay ganito ang hitsura:

ito ay "wròng wrìtten" string bùt I nèed to pù "sòme" special chà rs to see thèm, convertèd by fùnctìon!! at ano ito!

Kaya, sa pamamagitan ng pagkolekta ng ilang karagdagang impormasyon sa pahinang ito at pagsasama nito sa iba pang impormasyon sa iba pang mga pahina, nalutas ko ang problema sa solusyon na ito:

$finallyIDidIt = mb_convert_encoding($string, mysql_client_encoding($resourceID), mb_detect_encoding($string));

Ngayon sa aking database mayroon akong isang string na may tamang pag-encode.

Tandaan: Isang tala lamang para pangalagaan ang mysql_client_encoding function! Dapat ay konektado ka sa DB dahil nangangailangan ang function na ito ng resource ID bilang parameter.

Pero ok, ginagawa ko lang itong recoding bago ang aking INSERT, kaya hindi ito problema para sa akin.

Sana nakatulong ito sa isang taong tulad ng page na ito na tumulong sa akin!

Salamat sa lahat!

Ang kawili-wiling bagay tungkol sa mb_detect_encoding at mb_convert_encoding ay ang pagkakasunud-sunod ng mga pag-encode na iyong inaalok:

// Ang $input ay talagang UTF-8 mb_detect_encoding($input, "UTF-8", "ISO-8859-9, UTF-8"); // ISO-8859-9 (MALI!) mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9"); // UTF-8 (OK)

Sa ganitong paraan maaari kang gumamit ng isang partikular na pagkakasunud-sunod kapag tinutukoy ang mga inaasahang pag-encode. Gayunpaman, magkaroon ng kamalayan na ito ay hindi palya.

Echo mb_detect_encoding($str, "auto");

Echo mb_detect_encoding($str, "UTF-8, ASCII, ISO-8859-1");

Hindi ko talaga alam kung ano ang mga resulta, ngunit iminumungkahi kong kunin mo na lang ang ilan sa iyong mga channel na may iba't ibang pag-encode at subukan kung gumagana ang mb_detect_encoding o hindi.

Update
auto ay maikli para sa "ASCII, JIS, UTF-8, EUC-JP, SJIS". ibinabalik nito ang nakitang pag-encode, na magagamit mo para i-convert ang string sa utf-8 gamit ang iconv .

Hindi ko pa ito nasubukan, kaya walang garantiya. at baka may mas madaling paraan.

Ang bersyon na ito ay para sa wikang German, ngunit maaari mong baguhin ang $CHARSETS at $TESTCHARS

Class CharsetDetector ( pribadong static $CHARSETS = array("ISO_8859-1", "ISO_8859-15", "CP850"); pribadong static $TESTCHARS = array("€", "ä", "Ä", "ö", "Ö", "ü", "Ü", "ß"); public static function convert($string) ( return self::__iconv($string, self::getCharset($string)); ) public static function getCharset ($string) ($normalized = self::__normalize($string); if(!strlen($normalized))return "UTF-8"; $best = "UTF-8"; $charcountbest = 0; foreach (self ::$CHARSETS bilang $charset) ($str = self::__iconv($normalized, $charset); $charcount = 0; $stop = mb_strlen($str, "UTF-8"); for($idx = 0 ;< $stop; $idx++) { $char = mb_substr($str, $idx, 1, "UTF-8"); foreach (self::$TESTCHARS as $testchar) { if($char == $testchar) { $charcount++; break; } } } if($charcount>$charcountbest) ($charcountbest=$charcount; $best=$charset; ) //echo $text."
"; ) return $best; ) private static function __normalize($str) ($len = strlen($str); $ret = ""; for($i = 0; $i< $len; $i++){ $c = ord($str[$i]); if ($c >128) ( kung (($c > 247)) $ret .=$str[$i]; elseif ($c > 239) $bytes = 4; elseif ($c > 223) $bytes = 3; elseif ($ c > 191) $bytes = 2; kung hindi $ret .=$str[$i]; habang ($bytes > 1) ($i++; $b = ord($str[$i]); kung ($b< 128 || $b >191) ($ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;) iba pa $ret2.=$str[$i];

$bytes--;

) ) ) ibalik ang $ret; ) pribadong static na function __iconv($string, $charset) ( return iconv ($charset, "UTF-8" , $string); ) )

Ang pagpasa ng data ng utf8 sa isang latin1 table sa isang latin1 I/O session ay nagbibigay sa mga masasamang ibon na ito ng isang balahibo. Araw-araw ko itong nakikita sa mga retail store. Ang pabalik-balik ay maaaring mukhang tama. Ngunit ang phpmyadmin ay magpapakita ng katotohanan. Ang pagsasabi sa mysql kung anong encoding ang ipapasa mo ay magpoproseso ng mysql data para sa iyo.

Paano mabawi ang umiiral na mysql scrambled data ay isa pang tanong para sa talakayan.