Determinarea codificării textului în PHP - o prezentare generală a soluțiilor existente plus încă o bicicletă. Determinarea codificării textului în PHP și Python Php cum să aflați maparea codificării

02.04.2020 Știri

Am întâlnit o problemă - detectarea automată a paginii/textului/orice codificare. Sarcina nu este nouă și multe biciclete au fost deja inventate. In articol scurtă recenzie gasit pe net - plus propunerea a ceea ce cred ca este o solutie demna.

1. De ce nu mb_detect_encoding()?

Pe scurt, nu merge.

Hai sa vedem:
// La intrare - text rusesc în CP1251 codificare $string = iconv("UTF-8", "Windows-1251", "S-a apropiat de Anna Pavlovna, i-a sărutat mâna, expunându-i capul chel parfumat și strălucitor și calm s-a așezat pe canapea."); // Să vedem ce ne oferă md_detect_encoding(). Primul $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 // Acum $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
După cum puteți vedea, rezultatul este o mizerie completă. Ce facem când nu este clar de ce o funcție se comportă în acest fel? Așa e, hai să-l cautăm pe Google. Am găsit un răspuns grozav.

Pentru a risipi în sfârșit toate speranțele de a folosi mb_detect_encoding(), trebuie să vă uitați în codul sursă al extensiei mbstring. Deci, suflecați-vă mânecile și să mergem:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // linia 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + clic:
// 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 = el_encoding, elistszify , strict);...
Ctrl + clic:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * identifică codificarea */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Post text complet Nu voi folosi această metodă pentru a nu aglomera articolul cu surse inutile. Cei interesați se vor uita singuri. Suntem interesați de rândul numărul 593, unde verificăm de fapt dacă caracterul se potrivește cu codificarea:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_function)(*p, filtru); dacă (filtru->steagul) ( rău++; )
Iată principalele filtre pentru chirilice cu un singur octet:

Windows-1251 (comentariile originale păstrate)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* toate astea sunt atât de urâte acum! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filter) ( dacă (c >= 0x80 && c< 0xff) filter->steag = 0; altfel filtru->

KOI8-R
// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filter) ( dacă (c >= 0x80 && c< 0xff) filter->steag = 0; else filter->flag = 1; /* nu este */ returnează c; )

ISO-8859-5 (totul este distractiv aici)
// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter) ( return c; )
După cum puteți vedea, ISO-8859-5 returnează întotdeauna TRUE (pentru a returna FALSE, trebuie să setați filtru->flag = 1).

Când ne-am uitat la filtre, totul a căzut la loc. Nu există nicio modalitate de a distinge CP1251 de KOI8-R. În general, ISO-8859-5, dacă se află în lista de codificări, va fi întotdeauna detectat ca fiind corect.

În general, eșuează. Acest lucru este de înțeles - în general, este imposibil să aflați codificarea doar prin coduri de caractere, deoarece aceste coduri se intersectează în diferite codificări.

2. Ce aduce Google

Și Google aduce tot felul de mizerii. Nici nu voi posta aici sursa, uitați-vă singur dacă doriți (eliminați spațiul după http://, nu știu cum să arăt textul fără link):

Http://deer.org.ua/2009/10/06/1/
http://php.su/forum/topic.php?forum=1&topic=1346

3. Căutați după hub

1) din nou coduri de caractere:

2) după părerea mea, o soluție foarte interesantă:
Pro și contra în comentariul de pe link. Personal, cred că această soluție este redundantă doar pentru detectarea codificării - se dovedește a fi prea puternică. Definirea codificării în ea este un efect secundar).

4. De fapt, decizia mea

Ideea a apărut în timpul vizualizării celui de-al doilea link din secțiunea anterioară. Ideea este următoarea: luăm un text rusesc mare, măsurăm frecvențele diferitelor litere și folosim aceste frecvențe pentru a detecta codificarea. Privind în viitor, voi spune imediat că vor exista probleme cu literele mari și mici. Prin urmare, postez exemple de frecvențe de litere (să-i spunem „spectru”), atât cu majuscule și minuscule (în al doilea caz, am adăugat una și mai mare la o literă mică cu aceeași frecvență și am eliminat toate cele mai mari). În aceste „spectre” sunt decupate toate literele cu frecvențe mai mici de 0,001 și un spațiu. Iată ce am primit după procesarea „Război și pace”:

„spectru” cu majuscule și minuscule:
matrice ("o" => 0.095249209893009, "e" => 0.06836817536026, "a" => 0.067481298384992, "i" => 0.055995027400041, "052" => 0.067481298384992, "i" => 0.055995027400041, "05, 52" => 402. => 0,002252892226507, „N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "B" => 0,0014044332975731, "2975731, " 807" => 0,0015961610948418, "B" => 0,0014044332975731, "08" => 0,0012623590130186, „K” => 0,0011804488387602, „M” => 0,001061932790165,)

Nu ține seama de majuscule și minuscule:
matrice ("O" => 0.095249209893009, "o" => 0.095249209893009, "E" => 0.06836817536026, "e" => 0.06836817536026, "A67" => 9.02, "06" => 48. 067481298384992, „Și” => 0,055995027400041 , "i" => 0.055995027400041, .... "C" => 0.0029893589260344, "c" => 0.0029893589260344, "c" => 0.002464916350140, "01404" => 0.0029893589260344, "c" => 0.002464916350140, "01404" 6, „E” => 0,002252892226507, „e " => 0,002252892226507, "F" => 0,0015961610948418, "f" => 0,0015961610948418,)

Spectre în diferite codificări (cheile de matrice sunt codurile caracterelor corespunzătoare din codificarea corespunzătoare):

Mai departe. Luăm text dintr-o codificare necunoscută, pentru fiecare codificare verificată găsim frecvența caracterului curent și o adăugăm la „evaluarea” acestei codificări. Codificarea cu cea mai mare evaluare este cel mai probabil codificarea textului.

$encodings = array("cp1251" => necesită "specter_cp1251.php", "koi8r" => necesită "specter_koi8r.php", "iso88595" => necesită "specter_iso88595.php"); $enc_rates = array(); pentru ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)]; ) ) var_dump($enc_rates);
Nici măcar nu încercați să rulați singur acest cod - nu va funcționa. Puteți lua în considerare acest pseudocod - am omis detaliile pentru a nu aglomera articolul. $char_specter sunt exact matricele la care se face referire în pastebin.

rezultate
Rândurile tabelului sunt codificarea textului, coloanele sunt conținutul matricei $enc_rates.

1) $str = „Text rusesc”;
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

Totul e bine. Codificarea reală este deja de 4 ori rating mai mare decât restul - asta este într-un text atât de scurt. Pentru mai mult texte lungi raportul va fi aproximativ același.


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

Hopa! O mizerie completă. Asta pentru că literele mari din CP1251 corespund de obicei cu cele mici din KOI8-R. Și literele mici, la rândul lor, sunt folosite mult mai des decât cele mari. Deci definim șirul de majuscule în CP1251 ca KOI8-R.
Să încercăm să o facem fără a ține seama de majuscule și minuscule („spectre” nu țin cont de minuscule)

1) $str = „Text rusesc”;
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 MAJUSCULE TEXT RUSĂ";
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

După cum puteți vedea, codificarea corectă duce în mod constant cu „spectre” sensibile la majuscule (dacă linia conține un număr mic litere mari), și cu majuscule și minuscule. În cel de-al doilea caz, cu cele care nu țin seama de majuscule, liderul nu este atât de încrezător, desigur, dar destul de stabil chiar și pe linii mici. De asemenea, vă puteți juca cu greutățile literelor - faceți-le neliniare în raport cu frecvența, de exemplu.

5. Concluzie

Subiectul nu acoperă lucrul cu UTF-8 - nu există nicio diferență fundamentală aici, cu excepția faptului că obținerea codurilor de caractere și împărțirea șirului în caractere va fi ceva mai lungă/mai complexă.
Aceste idei pot fi extinse nu numai la codificări chirilice, desigur - întrebarea se află doar în „spectrurile” limbilor/codărilor corespunzătoare.

P.S. Dacă este cu adevărat necesar/interesant, atunci voi posta a doua parte a unei biblioteci complet funcționale pe GitHub. Deși cred că datele din postare sunt destul de suficiente pentru a scrie rapid o astfel de bibliotecă pentru a se potrivi propriilor nevoi - a fost stabilit „spectrul” pentru limba rusă, poate fi transferat cu ușurință în toate codificările necesare.

Citesc o mulțime de texte din diferite fluxuri RSS și le inserez în baza mea de date.

Desigur, există mai multe codificări diferite de caractere utilizate în conducte, de ex. UTF-8 și ISO-8859-1.

Din păcate, uneori apar probleme cu codificarea textului. Exemplu:

1) „ß” din „Fußball” ar trebui să arate așa în baza mea de date: „Ÿ”. Dacă este „Ÿ”, este afișat corect.

2) Uneori, „ß” din „Fußball” arată astfel în baza mea de date: „ß”. Apoi se afișează incorect, desigur.

3) În alte cazuri, „ß” este stocat ca „ß” – deci fără nicio modificare. Apoi se afișează și incorect.

Ce pot face pentru a evita cazurile 2 și 3?

Cum pot face totul la aceeași codificare, de preferință UTF-8? Când ar trebui să folosesc utf8_encode(), când ar trebui să folosesc utf8_decode() (este clar care este efectul, dar când ar trebui să folosesc funcții?) și când ar trebui să fac ceva cu intrarea?

Mă puteți ajuta și să-mi spuneți cum să fac aceeași codare? Poate cu funcția mb-detect-encoding()? Pot scrie o funcție pentru asta? Deci problemele mele sunt: ​​1) Cum să aflu ce codificare este folosită în text 2) Cum să o convertesc în UTF-8 - indiferent de codificarea veche

EDITAȚI | ×: Va funcționa această caracteristică?

Funcția corect_encoding($text) ( $current_encoding = mb_detect_encoding($text, "auto"); $text = iconv($current_encoding, "UTF-8", $text); return $text; )

L-am testat dar nu merge. Ce-i în neregulă cu el?

24 de răspunsuri

Dacă aplicați utf8_encode() unui șir UTF8 deja existent, acesta va returna o ieșire UTF8 deranjată.

Am creat o funcție care rezolvă toate aceste probleme. Se numește Encoding::toUTF8().

Nu trebuie să știți care este codificarea șirurilor dvs. Acesta poate fi Latin1 (iso 8859-1), Windows-1252 sau UTF8 sau șirul le poate conține. Encoding::toUTF8() convertește totul în UTF8.

Am făcut asta pentru că serviciul îmi dădea un flux de date, toate încurcate, amestecând UTF8 și Latin1 într-o singură linie.

Utilizare:

Require_once("Encoding.php"); utilizați \ForceUTF8\Encoding; // Acum este spațial de nume. $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

Am inclus o altă funcție, Encoding::fixUFT8(), care va repara fiecare șir UTF8 care pare deranjat.

Utilizare:

Require_once("Encoding.php"); utilizați \ForceUTF8\Encoding; // Acum este spațial de nume. $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 Fotbal Fédération Camerounaise de Fotbal Fédération Camerounaise de Fotbal Fédération Camerounaise de Fotbal

Actualizare: am convertit funcția (forceUTF8) într-o familie de funcții statice din clasa Encoding. Optiune noua- Codificare::toUTF8().

Mai întâi trebuie să determinați ce codificare a fost folosită. Deoarece analizați fluxuri RSS (eventual prin HTTP), ar trebui să citiți codificarea din parametrul set de caractere din câmpul Content-Type din antetul HTTP. Dacă lipsește, citiți codificarea din atributul de codificare al instrucțiunii de procesare. Dacă și aceasta lipsește, utilizați UTF-8 așa cum este definit în specificație.

Schimbare Iată ce voi face probabil:

Detectarea codificării este dificilă.

mb_detect_encoding funcționează prin ghicire pe baza mai multor candidați pe care îi treceți. În unele codificări, anumite secvențe de octeți sunt invalide, astfel încât se poate distinge între diferiți candidați. Din păcate, există multe codificări în care aceiași octeți sunt validi (dar diferiți). În aceste cazuri, este imposibil să se determine codificarea; Puteți implementa propria logică pentru a face presupuneri în aceste cazuri. De exemplu, datele care provin de la un site japonez vor fi cel mai probabil în codificare japoneză.

În timp ce aveți de-a face doar cu limbi vest-europene, să ne uităm la cele trei codificări principale: utf-8, iso-8859-1 și cp-1252. Deoarece acestea sunt valorile implicite pentru multe platforme, este posibil să fie raportate eronat. De exemplu. dacă oamenii folosesc codificări diferite, probabil că vor fi deschisi în privința asta, pentru că altfel lor software se va rupe foarte des. Deci, o strategie bună este să aveți încredere în furnizor, cu excepția cazului în care codificarea este declarată ca una dintre aceste trei. Ar trebui să dublezi totuși faptul că este de fapt valid folosind mb_check_encoding (rețineți că valid nu este același ca este - aceeași intrare poate fi valabilă pentru multe codificări). Dacă este unul dintre ele, puteți folosi mb_detect_encoding pentru a le diferenția. Din fericire, acest lucru este destul de determinist; Trebuie doar să utilizați secvența corectă de detectare, care este UTF-8, ISO-8859-1, WINDOWS-1252.

Odată ce ați descoperit codificarea, trebuie să o convertiți în reprezentarea internă (utf-8 este singura alegere rezonabilă). Funcția utf8_encode convertește iso-8859-1 în utf-8, astfel încât să poată fi utilizată numai pentru acel tip de intrare specific. Pentru alte codificări, utilizați mb_convert_encoding.

Această foaie de cheat listă câteva avertismente comune asociate cu manipularea UTF-8 în PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Această funcție, care detectează caractere multiocteți dintr-un șir, poate fi, de asemenea, utilă ():

Funcția detectUTF8($șir) ( return preg_match("%(?: [\xC2-\xDF][\x80-\xBF] # non-exagerat de 2 octeți |\xE0[\xA0-\xBF][\x80- \xBF] # excluzând supralungirile |[\xE1-\xEC\xEE\xEF][\x80-\xBF](2) # drept 3 octeți |\xED[\x80-\x9F][\x80-\xBF] # excluzând surogații |\xF0[\x90-\xBF][\x80-\xBF](2) # avioane 1-3 |[\xF1-\xF3][\x80-\xBF](3) # avioane 4- 15 |\xF4[\x80-\x8F][\x80-\xBF](2) # plan 16)+%xs", $șir); )

Un pic de atenție, ați spus că „ß” ar trebui să apară ca „Ÿ” în baza de date.

Acest lucru se datorează probabil faptului că utilizați o bază de date cu codificare de caractere latin1 sau poate că conexiunea php-mysql nu este configurată corect, php presupune că mysql-ul dvs. este configurat pentru a utiliza utf-8, așa că trimite datele ca utf8, dar dvs. mysql crede că php trimite date codificate ca iso-8859-1, așa că poate încerca din nou să codifice datele trimise ca utf-8, cauzând astfel de probleme.

Aruncă o privire la asta, s-ar putea să te ajute: http://php.net/manual/en/function.mysql-set-charset.php

Trebuie să verificați codificarea de pe intrare, deoarece răspunsurile pot fi codificate cu diferite codificări.
Forțez ca tot conținutul să fie trimis în UTF-8 făcând detectarea și traducerea folosind următoarea funcție:

Funcția fixRequestCharset() ( $ref = array(&$_GET, &$_POST, &$_REQUEST); foreach ($ref ca &$var) ( foreach ($var ca $key => $val) ( $encoding = mb_detect_encoding ($var[ $key ], mb_detect_order(), true); dacă (!$encoding) continuă; if (strcasecmp($encoding, "UTF-8") != 0) ( $encoding = iconv($encoding, " UTF-8", $var[ $key ]); dacă ($encoding === false) continuă; $var[ $key ] = $encoding; ) ) ) )

Această procedură va transforma totul variabile PHP, care provin de la gazda la distanță în UTF-8.
Sau ignorați valoarea dacă codificarea nu poate fi detectată sau convertită.
Îl poți personaliza în funcție de nevoile tale.
Doar sunați-l înainte de a utiliza variabile.

Codificarea dvs. pare că sunteți codificat în UTF-8 de două ori; adică de la o altă codificare, la UTF-8 și din nou la UTF-8. Este ca și cum ați fi convertit iso-8859-1 din iso-8859-1 în utf-8 și tratat cu o linie nouă ca iso-8859-1 pentru o altă conversie în UTF-8.

Iată un pseudocod pentru ceea ce ai făcut:

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

Trebuie sa incerci:

  • detectați codificarea folosind mb_detect_encoding() sau orice doriți să utilizați
  • dacă UTF-8, convertiți la iso-8859-1 și repetați pasul 1
  • în cele din urmă, convertiți înapoi în UTF-8

Se presupune că în conversia „medie” ați folosit iso-8859-1. Dacă ați folosit Windows-1252, convertiți-l în Windows-1252 (latin1). Codificarea originală a sursei nu este importantă; cel pe care l-ai folosit în a doua conversie eronată.

Aceasta este presupunerea mea cu privire la ceea ce sa întâmplat; ai putea face ceva mai mult pentru a obține patru octeți în loc de un octet ASCII extins.

Germana folosește și iso-8859-2 și windows-1250 (latin2).

Proiectarea codificării caracterelor fluxurilor RSS pare complicată. Chiar și paginile web obișnuite omit sau mint adesea despre codificarea lor.

Deci, puteți încerca să utilizați modul corect de a detecta codificarea și apoi să reveniți la o formă de detectare automată (ghicire).

Știu că aceasta este o întrebare veche, dar cred că un răspuns util nu strica niciodată. Am probleme cu codificarea mea între aplicațiile desktop, variabilele SQLite și GET/POST. Unele dintre ele vor fi în UTF-8, altele vor fi în ASCII și, în mare parte, lucrurile vor deveni confuze atunci când sunt implicate personaje străine.

Iată soluția mea. Vă netezește GET/POST/REQUEST (am ratat cookie-uri, dar le puteți adăuga dacă este necesar) la fiecare încărcare a paginii înainte de procesare. Funcționează bine în antet. PHP va emite avertismente dacă nu poate determina automat codarea sursă, astfel încât aceste avertismente sunt suprimate folosind @.

//Conversia totul din varsurile noastre în UTF-8 pentru a juca frumos cu baza de date... //Folosiți o detectare automată aici pentru a ne ajuta să nu codificăm dublu... //Suprimați posibilele avertismente cu @ pentru când codificarea nu poate fi detectată încercați ( $proces = array(&$_GET, &$_POST, &$_REQUEST); în timp ce (listă($cheie, $val) = fiecare($proces)) ( foreach ($val ca $k => $v) ( unset($process[$key][$k]); if (is_array($v)) ( $process[$key][@mb_convert_encoding($k,"UTF-8","auto")] = $ v; $proces = &$proces[$key][@mb_convert_encoding($k,"UTF-8","auto")]; ) else ( $process[$key][@mb_convert_encoding($k,"UTF- 8","auto")] = @mb_convert_encoding($v,"UTF-8","auto"); ) ) ) unset($proces); ) catch(Excepție $ex)()

Am căutat soluții de codare cu AGES și această pagină este probabil sfârșitul anilor de căutare! Am verificat câteva dintre sugestiile pe care le-ați menționat și iată notele mele:

Aceasta este linia mea de testare:

aceasta este linia „wròng wrìtten” pentru care nu am folosit-o setări speciale Chàrs să le vadă, convertite prin fùnctìon!! Deci ce este asta!

Fontul paginii mele este UTF-8

Dacă fac INSERT în acest fel, am câteva caractere în DB care probabil provin de pe Marte... așa că trebuie să le convertesc în UTF-8 „sensible”. Am încercat utf8_encode() dar caracterele extraterestre îmi invadau baza de date...

Deci, am încercat să folosesc funcția forceUTF8 situată la numărul 8, dar în DB șirul salvat arată astfel:

acesta este șir "wròng wrìtten" dar nu am avut nevoie de "câmâi" versuri speciale pentru a le vedea, convertite de fùnctìon!! Deci ce este asta!

Deci, adunând mai multe informații pe această pagină și combinându-le cu alte informații de pe alte pagini, am rezolvat problema cu această soluție:

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

Acum, în baza mea de date am un șir cu codificarea corectă.

Notă: Doar o notă pentru a avea grijă de funcția mysql_client_encoding! Trebuie să fiți conectat la DB deoarece această funcție necesită un ID de resursă ca parametru.

Dar ok, fac această recodificare înainte de INSERT, așa că nu este o problemă pentru mine.

Sper că acest lucru va ajuta cineva ca această pagină m-a ajutat!

Multumesc tuturor!

Lucrul interesant despre mb_detect_encoding și mb_convert_encoding este că ordinea codificărilor pe care le oferiți contează:

// $input este de fapt UTF-8 mb_detect_encoding($input, "UTF-8", "ISO-8859-9, UTF-8"); // ISO-8859-9 (GRÉS!) mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9"); // UTF-8 (OK)

În acest fel, puteți utiliza o anumită ordine atunci când specificați codificările așteptate. Cu toate acestea, rețineți că acest lucru nu este sigur.

Echo mb_detect_encoding($str, "auto");

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

Nu știu cu adevărat care sunt rezultatele, dar vă sugerez să luați câteva dintre canalele dvs. cu diferite codificări și să încercați dacă mb_detect_encoding funcționează sau nu.

Actualizați
auto este prescurtarea pentru „ASCII, JIS, UTF-8, EUC-JP, SJIS”. returnează codificarea detectată, pe care o puteți folosi pentru a converti șirul în utf-8 cu iconv .

Nu l-am testat, deci nu există garanții. și poate că există o cale mai ușoară.

Această versiune este pentru Limba germană, dar puteți modifica $CHARSETS și $TESTCHARS

Clasa CharsetDetector ( private static $CHARSETS = array("ISO_8859-1", "ISO_8859-15", "CP850"); private static $TESTCHARS = array ("€", "ä", "Ä", "ö", „Ö”, „ü”, „Ü”, „ß”); funcție publică statică convert($șir) ( return self::__iconv($șir, self::getCharset($șir)); ) funcție publică statică getCharset ($șir) ( $normalized = self::__normalize($string); if(!strlen($normalized))return „UTF-8”; $best = „UTF-8”; $charcountbest = 0; foreach (self ::$CHARSETS ca $carset) ( $str = self::__iconv($normalized, $charset); $charcount = 0; $stop = mb_strlen($str, "UTF-8"); for($idx = 0 ; $idx< $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=$carset; ) //echo $text."
"; ) returnează $best; ) funcție statică privată __normalize($str) ( $len = strlen($str); $ret = ""; for($i = 0; $i< $len; $i++){ $c = ord($str[$i]); if ($c >128) ( if (($c > 247)) $ret .=$str[$i]; elseif ($c > 239) $bytes = 4; elseif ($c > 223) $bytes = 3; elseif ($ c > 191) $bytes = 2; altfel $ret .=$str[$i]; dacă (($i + $bytes) > $len) $ret .=$str[$i]; $ret2=$str [$i]; în timp ce ($octeți > 1) ( $i++; $b = ord($str[$i]); dacă ($b< 128 || $b >191) ($ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;) else $ret2.=$str[$i]; $octeți--; ) ) ) return $ret; ) funcție statică privată __iconv($șir, $carset) ( return iconv ($charset, "UTF-8" , $șir); ) )

După ce v-ați sortat scripturile php, nu uitați să spuneți mysql ce codificare transmiteți și doriți să o primiți.

Exemplu: setarea setului de caractere la utf8

Trecerea datelor utf8 la un tabel latin1 într-o sesiune de I/O latin1 le oferă acestor păsări urâte o pană. Văd asta în fiecare zi în magazinele cu amănuntul. Înainte și înapoi poate părea corect. Dar phpmyadmin va arăta adevărul. Spuneți lui mysql ce codificare o transmiteți va procesa date mysql Pentru dumneavoastră.

Cum să recuperați datele amestecate mysql existente este o altă întrebare de discuție. :)

Există o problemă: cum să determinați rapid codificarea șir de textîn raport cu UTF-8, din ce în ce mai mult, trebuie să lucrăm cu șiruri în codificare UNICODE.

Mai jos este o funcție pentru a verifica dacă codarea UNICODE (UTF-8) trebuie convertită în codificare WINDOWS (win-1251)

Funcția oferă un răspuns destul de precis, deși nu se bazează pe conversia caracter cu cod.

funcţie detect_my_utf($s)( $s=urlencode($s); // în unele cazuri - o operație inutilă (comentare) $res="0"; $j=strlen($s); $s2=strtoupper($ s); $s2=str_replace("%D0","",$s2); $s2=str_replace("%D1","",$s2); $k=strlen($s2); $m=1 ; dacă ($k>0)( $m=$j/$k; dacă (($m>1.2)&&($m

Scurtă descriere a funcției detect_my_utf():

  • converti (șir în format special)
  • calculați lungimea șirului de intrare
  • scrieți cu majuscule toate literele șirului
  • eliminați codurile specifice %D0 și %D1
  • calculați lungimea linie nouă
  • obținem raportul dintre linia veche și cea nouă

Dacă acest raport este 1 sau aproape de acesta, atunci se suspectează că șirul de intrare nu a fost codificat în UNICODE. Dacă acest raport este în intervalul de la 1,2 la 2,2, atunci puteți recoda în siguranță șirul în codificarea WINDOWS win-1251.

Ieșirea funcției este 0 sau, respectiv, 1, nu UNICODE sau UNICODE.

Exemple de execuție a funcției:

Linie de intrare: РїР?С?С?Р?Р?Рє С?Р?Р·Р?Р°Р?РёС? Р°Р?РёР?Р°С+РёРё Р? imageready Șir convertit: %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 Rezultatul funcției: 1 frază codificată: ordinea creării animației în imageready

Șir de intrare: R?S?R?R?R?S

Șir de intrare: РїС?Р?Р?С?Р°Р?Р?Р° С+С"РчР?РёС? РїР?С+Р°С?апаР?Р?С

Șir de intrare: ghid de desen Șir convertit: %EF%EE%F1%EE%E1%E8%E5 %EF%EE %F0%E8%F1%EE%E2%E0%ED%E8%FE Rezultat funcție: 0 Fraza codificată : ghid de desen Acest algoritm se descurcă bine cu o varietate de șiruri de caractere primite ca parte a serviciului de statistici de conversie a motorului de căutare.

Materiale interesante de pe site:

  • Un articol despre interesul site-ului pentru motorul de căutare. Poate că unele dintre materiale sunt deja depășite după 10 ani, dar unele puncte merită să le acordați atenție.

  • Opinia dvs. asupra problemei schimbului de hyperlinkuri între un site donator și site-urile destinatare.

  • Un alt hack de viață. Învingem jucători necinstiți în jocul „Balda”. O bază de date mare de cuvinte care poate fi extinsă cu ușurință.

Am întâlnit o problemă - detectarea automată a paginii/textului/orice codificare. Sarcina nu este nouă și multe biciclete au fost deja inventate. Articolul conține o scurtă prezentare a ceea ce s-a găsit pe Internet - plus o propunere a ceea ce cred că este o soluție demnă.

1. De ce nu mb_detect_encoding()?

Pe scurt, nu merge.

Hai sa vedem:
// La intrare - text rusesc în CP1251 codificare $string = iconv("UTF-8", "Windows-1251", "S-a apropiat de Anna Pavlovna, i-a sărutat mâna, expunându-i capul chel parfumat și strălucitor și calm s-a așezat pe canapea."); // Să vedem ce ne oferă md_detect_encoding(). Primul $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 // Acum $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
După cum puteți vedea, rezultatul este o mizerie completă. Ce facem când nu este clar de ce o funcție se comportă în acest fel? Așa e, hai să-l cautăm pe Google. Am găsit un răspuns grozav.

Pentru a risipi în sfârșit toate speranțele de a folosi mb_detect_encoding(), trebuie să vă uitați în codul sursă al extensiei mbstring. Deci, suflecați-vă mânecile și să mergem:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // linia 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + clic:
// 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 = el_encoding, elistszify , strict);...
Ctrl + clic:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * identifică codificarea */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Nu voi posta textul integral al metodei, pentru a nu aglomera articolul cu surse inutile. Cei interesați se vor uita singuri. Suntem interesați de rândul numărul 593, unde verificăm de fapt dacă caracterul se potrivește cu codificarea:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_function)(*p, filtru); dacă (filtru->steagul) ( rău++; )
Iată principalele filtre pentru chirilice cu un singur octet:

Windows-1251 (comentariile originale păstrate)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* toate astea sunt atât de urâte acum! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filter) ( dacă (c >= 0x80 && c< 0xff) filter->steag = 0; altfel filtru->

KOI8-R
// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filter) ( dacă (c >= 0x80 && c< 0xff) filter->steag = 0; else filter->flag = 1; /* nu este */ returnează c; )

ISO-8859-5 (totul este distractiv aici)
// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter) ( return c; )
După cum puteți vedea, ISO-8859-5 returnează întotdeauna TRUE (pentru a returna FALSE, trebuie să setați filtru->flag = 1).

Când ne-am uitat la filtre, totul a căzut la loc. Nu există nicio modalitate de a distinge CP1251 de KOI8-R. În general, ISO-8859-5, dacă se află în lista de codificări, va fi întotdeauna detectat ca fiind corect.

În general, eșuează. Acest lucru este de înțeles - în general, este imposibil să aflați codificarea doar prin coduri de caractere, deoarece aceste coduri se intersectează în diferite codificări.

2. Ce aduce Google

Și Google aduce tot felul de mizerii. Nici nu voi posta aici sursa, uitați-vă singur dacă doriți (eliminați spațiul după http://, nu știu cum să arăt textul fără link):

Http://deer.org.ua/2009/10/06/1/
http://php.su/forum/topic.php?forum=1&topic=1346

3. Căutați după hub

1) din nou coduri de caractere: habrahabr.ru/blogs/php/27378/#comment_710532

2) dupa parerea mea, o solutie foarte interesanta: habrahabr.ru/blogs/php/27378/#comment_1399654
Pro și contra în comentariul de pe link. Personal, cred că această soluție este redundantă doar pentru detectarea codificării - se dovedește a fi prea puternică. Definirea codificării în ea este un efect secundar).

4. De fapt, decizia mea

Ideea a apărut în timpul vizualizării celui de-al doilea link din secțiunea anterioară. Ideea este următoarea: luăm un text rusesc mare, măsurăm frecvențele diferitelor litere și folosim aceste frecvențe pentru a detecta codificarea. Privind în viitor, voi spune imediat că vor exista probleme cu literele mari și mici. Prin urmare, postez exemple de frecvențe de litere (să-i spunem „spectru”), atât cu majuscule și minuscule (în al doilea caz, am adăugat una și mai mare la o literă mică cu aceeași frecvență și am eliminat toate cele mai mari). În aceste „spectre” sunt decupate toate literele cu frecvențe mai mici de 0,001 și un spațiu. Iată ce am primit după procesarea „Război și pace”:

„spectru” cu majuscule și minuscule:
matrice ("o" => 0.095249209893009, "e" => 0.06836817536026, "a" => 0.067481298384992, "i" => 0.055995027400041, "052" => 0.067481298384992, "i" => 0.055995027400041, "05, 52" => 402. => 0,002252892226507, „N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "B" => 0,0014044332975731, "2975731, " 807" => 0,0015961610948418, "B" => 0,0014044332975731, "08" => 0,0012623590130186, „K” => 0,0011804488387602, „M” => 0,001061932790165,)

Nu ține seama de majuscule și minuscule:
matrice ("O" => 0.095249209893009, "o" => 0.095249209893009, "E" => 0.06836817536026, "e" => 0.06836817536026, "A67" => 9.02, "06" => 48. 067481298384992, „Și” => 0,055995027400041 , "i" => 0.055995027400041, .... "C" => 0.0029893589260344, "c" => 0.0029893589260344, "c" => 0.002464916350140, "01404" => 0.0029893589260344, "c" => 0.002464916350140, "01404" 6, „E” => 0,002252892226507, „e " => 0,002252892226507, "F" => 0,0015961610948418, "f" => 0,0015961610948418,)

Spectre în diferite codificări (cheile de matrice sunt codurile caracterelor corespunzătoare din codificarea corespunzătoare):

Mai departe. Luăm text dintr-o codificare necunoscută, pentru fiecare codificare verificată găsim frecvența caracterului curent și o adăugăm la „evaluarea” acestei codificări. Codificarea cu cea mai mare evaluare este cel mai probabil codificarea textului.

$encodings = array("cp1251" => necesită "specter_cp1251.php", "koi8r" => necesită "specter_koi8r.php", "iso88595" => necesită "specter_iso88595.php"); $enc_rates = array(); pentru ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)]; ) ) var_dump($enc_rates);
Nici măcar nu încercați să rulați singur acest cod - nu va funcționa. Puteți lua în considerare acest pseudocod - am omis detaliile pentru a nu aglomera articolul. $char_specter sunt exact matricele la care se face referire în pastebin.

rezultate
Rândurile tabelului sunt codificarea textului, coloanele sunt conținutul matricei $enc_rates.

1) $str = „Text rusesc”;
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

Totul e bine. Codificarea reală are deja o evaluare de 4 ori mai mare decât celelalte - aceasta este pentru un text atât de scurt. Pentru textele mai lungi raportul va fi aproximativ același.


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

Hopa! O mizerie completă. Asta pentru că literele mari din CP1251 corespund de obicei cu cele mici din KOI8-R. Și literele mici, la rândul lor, sunt folosite mult mai des decât cele mari. Deci definim șirul de majuscule în CP1251 ca KOI8-R.
Să încercăm să o facem fără a ține seama de majuscule și minuscule („spectre” nu țin cont de minuscule)

1) $str = „Text rusesc”;
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 MAJUSCULE TEXT RUSĂ";
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

După cum puteți vedea, codificarea corectă conduce în mod constant atât cu „spectre” sensibile la majuscule (dacă linia conține un număr mic de litere majuscule), cât și cu cele care nu țin cont de majuscule. În cel de-al doilea caz, cu cele care nu țin seama de majuscule, liderul nu este atât de încrezător, desigur, dar destul de stabil chiar și pe linii mici. De asemenea, vă puteți juca cu greutățile literelor - faceți-le neliniare în raport cu frecvența, de exemplu.

5. Concluzie

Subiectul nu acoperă lucrul cu UTF-8 - nu există nicio diferență fundamentală aici, cu excepția faptului că obținerea codurilor de caractere și împărțirea șirului în caractere va fi ceva mai lungă/mai complexă.
Aceste idei pot fi extinse nu numai la codificări chirilice, desigur - întrebarea se află doar în „spectrurile” limbilor/codărilor corespunzătoare.

P.S. Dacă este cu adevărat necesar/interesant, atunci voi posta a doua parte a unei biblioteci complet funcționale pe GitHub. Deși cred că datele din postare sunt destul de suficiente pentru a scrie rapid o astfel de bibliotecă pentru a se potrivi propriilor nevoi - a fost stabilit „spectrul” pentru limba rusă, poate fi transferat cu ușurință în toate codificările necesare.

Idee - Loterie

Nu mi-a venit ideea de a obține codificarea, dar, din păcate, nu vă pot spune autorul acum, deoarece a fost acum aproximativ 4 ani și de unde am obținut aceste informații a fost uitat de mult. Autorul a propus o definiție și a arătat un exemplu pentru 1-2 codificări în Python. Simplitatea soluției sale nu m-a lăsat deoparte și am dezvoltat-o ​​până la rezultatul dorit.
Esența ideii constă în tabelele de codificare în sine. După cum știți, orice codificare conține propriul său tabel de coduri și fiecărui caracter de codificare îi este atribuită o anumită valoare. Nu voi afișa aici tabele de codificare; acum sunt destul de ușor de găsit pe Internet.
Principiul implementării este următorul:
  1. Este creată o variabilă matrice pentru a stoca rezultatul „analizei” textului verificat. Fiecare element al matricei va conține rezultatul pentru o anumită codificare.
  2. Textul primit ca intrare în funcție este repetat simbolic.
  3. Ordinalul (sensul acelui caracter) este luat din fiecare caracter și comparat cu intervalul de codificare.
  4. Dacă valoarea se încadrează pe un caracter cu majuscule (majuscule), valoarea 1 este adăugată elementului de matrice care stochează rezultatul acestei codificări.
  5. Dacă valoarea se încadrează pe un caracter mic (mic), valoarea 3 este adăugată elementului de matrice care stochează rezultatul acestei codificări.
  6. Acea codificare, sau mai precis, elementul matricei care stochează rezultatul codificării sale, care a obținut cele mai multe puncte, este cel mai probabil codificarea originală.
Acest algoritm este valabil pentru codificări pe un singur octet, cum ar fi KOI-8, CP1251 (windows-1251) și altele. Cu toate acestea, pentru codificări pe doi octeți (UTF-8 în cazul meu), această abordare va produce un rezultat eronat. Pentru început, am încercat să rezolv această problemă adăugând 5 pentru caracterele majuscule și 7 pentru caracterele minuscule. Rezultatul a devenit mai bun, dar erorile de recunoaștere erau încă prezente. După câteva experimente, am ajuns la concluzia că pentru a determina corect UTF, pentru caracterele majuscule, ar trebui adăugat la rezultat 10, pentru caracterele mici, 14, adică de 2 ori mai mult decât estimarea mea inițială. Cu toate acestea, pentru o mai bună înțelegere vizuală a codului, am lăsat 5 și, respectiv, 7 pentru caracterele UTF, iar în timpul testării am crescut aceste valori cu 2 și le-am adăugat la rezultat.
Acesta este practic tot algoritmul. Și fără bătăi de cap inutile.
Majoritatea timpului petrecut cu implementarea acestei funcții a fost, desigur, căutarea tabelelor de coduri și aranjarea corectă a intervalelor. Nu numai că a fost destul de dificil să găsesc tabelul de cod curent la momentul când am scris prima dată această funcție, dar și intervalele de caractere din ele sar la întâmplare. Cu toate acestea, apoi m-am hotărât pe cele mai actuale (și până astăzi) codificări: UTF-8, CP1251, KOI8-R, IBM866, ISO-8859-5 și MAC. Dacă aceste codificări nu sunt suficiente pentru dvs., vă puteți baza pe a acestui algoritm adauga cod.

De la cuvinte la practică

De fapt, întregul cod al funcției din Python arată astfel:

Codificări = ( „UTF-8”: „utf-8”, „CP1251”: „windows-1251”, „KOI8-R”: „koi8-r”, „IBM866”: „ibm866”, „ISO-8859- 5": "iso-8859-5", "MAC": "mac", ) """ Determinarea codificării textului """ def get_codepage(str = None): majuscule = 1 minuscule = 3 utfupper = 5 utflower = 7 codepages = () pentru enc în encodings.keys(): codepages = 0 dacă str nu este None și len(str) > 0: last_simb = 0 pentru simb în str: simb_ord = ord(simb) """caractere non-rusești " "" dacă simb_ord< 128 or simb_ord >256: continuați """UTF-8""" dacă last_simb == 208 și (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 = pagini de cod idx = returnare articol idx
Exemplu de apel de funcție

Imprimați codificări

Ce zici de PHP?

Rescrierea unei funcții gata făcute din Python în PHP nu a fost dificilă. În aparență, practic nu este diferit de părintele său în Python:

/** * Determinați codarea textului * @param String $text Text * @return String Codificare text */ function get_codepage($text = "") ( if (!empty($text)) ( $utflower = 7; $utfupper = 5; $minuscule = 3; $majuscule = 1; $last_simb = 0; $charsets = array("UTF-8" => 0, "CP1251" => 0, "KOI8-R" => 0, "IBM866 " => 0, "ISO-8859-5" => 0, "MAC" => 0,); pentru ($a = 0; $a< strlen($text); $a++) { $char = ord($text[$a]); // non-russian characters if ($char<128 || $char>256) continua; // UTF-8 dacă (($last_simb==208) && (($char>143 && $car<176) || $char==129)) $charsets["UTF-8"] += ($utfupper * 2); if ((($last_simb==208) && (($char>175 && $car<192) || $char==145)) || ($last_simb==209 && $char>127 && $car<144)) $charsets["UTF-8"] += ($utflower * 2); // CP1251 if (($char>223 && $car<256) || $char==184) $charsets["CP1251"] += $lowercase; if (($char>191 && $car<224) || $char==168) $charsets["CP1251"] += $uppercase; // KOI8-R if (($char>191 && $car<224) || $char==163) $charsets["KOI8-R"] += $lowercase; if (($char>222 && $car<256) || $char==179) $charsets["KOI8-R"] += $uppercase; // IBM866 if (($char>159 && $car<176) || ($char>223 && $car<241)) $charsets["IBM866"] += $lowercase; if (($char>127 && $car<160) || $char==241) $charsets["IBM866"] += $uppercase; // ISO-8859-5 if (($char>207 && $car<240) || $char==161) $charsets["ISO-8859-5"] += $lowercase; if (($char>175 && $car<208) || $char==241) $charsets["ISO-8859-5"] += $uppercase; // MAC if ($char>221 && $car<255) $charsets["MAC"] += $lowercase; if ($char>127 && $car<160) $charsets["MAC"] += $uppercase; $last_simb = $char; } arsort($charsets); return key($charsets); } }
Exemplu de apel de funcție

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

LikBez sau Nu interferați cu funcționarea mașinii

Nu ar trebui să încercați să testați această funcție. Din algoritm reiese clar că, cu cât primește mai puțin text ca intrare, cu atât este mai mare probabilitatea ca funcția să recunoască codificarea incorect. Pe de altă parte, volumele de hrănire ale lui Lev Tolstoi nu au nici un sens: această metodă se descurcă bine cu o propoziție mică de 100-200 de caractere. Și deși în exemplele apelului la intrare am trimis întregul conținut al unui anumit fișier „test.txt”, care trebuia să conțină text a cărui codificare trebuie determinată, o mică secțiune de text poate (și ar trebui) să fie trecut la intrarea funcției.
Consider că perversiunile cu litere mari și mici mixte nu sunt, în general, adecvate în acest caz, deoarece această metodă a fost scrisă pentru o sarcină obișnuită, obișnuită, cu aproximativ limba rusă alfabetizată. Și astfel de experimente îmi amintesc cel mai adesea de o glumă:

O fabrică rusă de prelucrare a lemnului a achiziționat o unitate japoneză. Muncitorii ruși s-au adunat în jurul lui și să ne dăm seama cum lucrează. Unul a luat tabla și a băgat-o în ea. Unitate:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz Băieți: Wow!!! Unitatea expusă: ei bine, ce ai părut? Un altul a luat un buștean netăiat și l-a introdus în unitate. Unitate:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz Băieți: Wow!!! Unitatea expusă: ei bine, ce ai părut? Al treilea bărbat nu a suportat-o, a tras o șină de undeva și a înfipt-o în unitate. Unitate: drrrrrrr-tyh-tyh-tyh... A început să fumeze și pe afișaj scrie: Wow!!! Baieti: pai ce v-ati gandit!!!
Deci, pentru astfel de teste răsucite veți avea nevoie cel mai probabil de un algoritm răsucit, ceea ce această funcție nu este. Și din practică voi spune că în timpul utilizării mele de 4 ani, această metodă nu m-a dezamăgit niciodată și a dat întotdeauna rezultatul potrivit.
Sper că articolul meu va fi de folos cuiva.
Vă mulțumim pentru atenție.

Când utilizați tot sau o parte din conținut, nu uitați să furnizați un link către sursă, adică către blogul meu.