Određivanje kodiranja teksta u PHP-u - pregled postojećih rješenja plus još jedan bicikl. Određivanje kodiranja teksta u PHP-u i Python Php kako saznati mapiranje kodiranja

02.04.2020 Vijesti

Naišao sam na problem - automatsko otkrivanje stranice/teksta/bilo kojeg kodiranja. Zadatak nije nov, a mnogi bicikli su već izumljeni. U članku kratki osvrt našao na netu - plus prijedlog za što mislim da je vrijedno rješenje.

1. Zašto ne mb_detect_encoding()?

Ukratko, ne ide.

Gledajmo:
// Na ulazu - ruski tekst u CP1251 koji kodira $string = iconv("UTF-8", "Windows-1251", "Prišao je Ani Pavlovnoj, poljubio joj ruku, otkrivajući joj svoju namirisanu i blistavu ćelavu glavu, i mirno sjeo na sofu."); // Da vidimo što nam md_detect_encoding() daje. Prvo $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 // Sada $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
Kao što vidite, rezultat je potpuni nered. Što radimo kada nije jasno zašto se neka funkcija tako ponaša? Tako je, proguglajmo. Našao sam odličan odgovor.

Kako biste konačno raspršili sve nade za korištenje mb_detect_encoding(), morate pogledati izvorni kod ekstenzije mbstring. Dakle, zasučite rukave i idemo:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // linija 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + klik:
// ext/mbstring/libmbfl/mbfl/mbfilter.c: 643 const char *mbfl_identify_encoding_name (mbfl_string *string, enum mbfl_no_encoding *elist, incint, strict) (const mbfl_encoding; , strog); ...
Ctrl + klik:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * identificiraj kodiranje */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Post puni tekst Neću koristiti ovu metodu kako ne bih zatrpao članak nepotrebnim izvorima. Zainteresirani će sami pogledati. Zanima nas linija broj 593, gdje zapravo provjeravamo odgovara li znak kodiranju:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_function)(*p, filter); ako (filter->zastavica) (loš++;)
Evo glavnih filtera za jednobajtnu ćirilicu:

Windows-1251 (izvorni komentari sačuvani)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* sve je ovo sada tako ružno! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filter) ( if (c >= 0x80 && c< 0xff) filter->zastava = 0; inače filter->

KOI8-R
// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filter) ( if (c >= 0x80 && c< 0xff) filter->zastava = 0; inače filter->zastavica = 1; /* nije to */ return c; )

ISO-8859-5 (ovdje je sve zabavno)
// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter) ( return c; )
Kao što vidite, ISO-8859-5 uvijek vraća TRUE (za vraćanje FALSE, trebate postaviti filter->flag = 1).

Kad smo pogledali filtere, sve je sjelo na svoje mjesto. Ne postoji način da se razlikuje CP1251 od KOI8-R. Općenito, ISO-8859-5, ako je na popisu kodiranja, uvijek će biti otkriven kao točan.

Općenito, neuspjeh. To je razumljivo - općenito je nemoguće saznati kodiranje samo pomoću kodova znakova, budući da se ti kodovi sijeku u različitim kodovima.

2. Što Google donosi

A Google donosi svakakve bedarije. Ovdje neću ni postavljati izvor, pogledajte sami ako želite (maknite razmak nakon http://, ne znam kako prikazati tekst bez linka):

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

3. Pretraživanje po čvorištu

1) opet kodovi znakova:

2) po mom mišljenju, vrlo zanimljivo rješenje:
Za i protiv u komentaru na poveznici. Osobno mislim da je ovo rješenje suvišno samo za detekciju kodiranja - ispada da je previše moćno. Definiranje kodiranja u njemu je nuspojava).

4. Zapravo, moja odluka

Ideja je nastala prilikom pregledavanja drugog linka iz prethodnog odjeljka. Ideja je sljedeća: uzmemo veliki ruski tekst, izmjerimo frekvencije različitih slova i pomoću tih frekvencija detektiramo kodiranje. Gledajući unaprijed, odmah ću reći da će biti problema s velikim i malim slovima. Stoga objavljujem primjere učestalosti slova (nazovimo to "spektar"), i velikih i malih slova (u drugom slučaju sam malom slovu iste frekvencije dodao još veće i uklonio sve one veće). U tim "spektrima" sva su slova s ​​frekvencijama manjim od 0,001 i razmakom izrezana. Ovo sam dobio nakon obrade "Rata i mira":

"Spektar" koji razlikuje velika i mala slova:
niz ("o" => 0,095249209893009, "e" => 0,06836817536026, "a" => 0,067481298384992, "i" => 0,055995027400041, "n" => 0,052242744063325, ... . "e" => 0,002252892226507, "N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "B" => 0,0014044332975731, "O" => 0,0013188987793209 , "A" => 0,0012623590130186, "K" => 0,0011804488387602, "M" => 0,001061932790165,)

Neosjetljivo na velika i mala slova:
niz ("O" => 0,095249209893009, "o" => 0,095249209893009, "E" => 0,06836817536026, "e" => 0,06836817536026, "A" => 0,067481298384992, " a " => 0,067481298384992, "I" => 0,055995027400041 , "i" => 0,055995027400041, .... "C" => 0,0029893589260344, "c" => 0,0029893589260344, "c" => 0,0024649163501406, "c" => 0,00246491635 01406, "E" => 0,002252892226507, "e " => 0,002252892226507, "F" => 0,0015961610948418, "f" => 0,0015961610948418,)

Spektri u različitim kodovima (ključevi polja su kodovi odgovarajućih znakova u odgovarajućem kodiranju):

Unaprijediti. Uzimamo tekst nepoznatog kodiranja, za svako kodiranje koje se provjerava nalazimo učestalost trenutnog znaka i dodajemo ga "ocjeni" ovog kodiranja. Kodiranje s najvišom ocjenom najvjerojatnije je kodiranje teksta.

$encodings = array("cp1251" => zahtijevaju "specter_cp1251.php", "koi8r" => zahtijevaju "specter_koi8r.php", "iso88595" => zahtijevaju "specter_iso88595.php"); $enc_rates = array(); za ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)]; ) ) var_dump($enc_rates);
Nemojte ni pokušavati sami pokrenuti ovaj kôd - neće uspjeti. Možete uzeti u obzir ovaj pseudokod - izostavio sam detalje kako ne bih zatrpao članak. $char_specter su upravo oni nizovi koji su navedeni u pastebinu.

rezultate
Redovi tablice su kodiranje teksta, stupci su sadržaj niza $enc_rates.

1) $str = "Ruski tekst";
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

Sve je u redu. Pravo kodiranje je već 4 puta viša ocjena nego ostali – ovako je u kratkom tekstu. Za više dugi tekstovi omjer će biti približno isti.


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

Ups! Potpuni nered. To je zato što velika slova u CP1251 obično odgovaraju malim u KOI8-R. A mala slova, zauzvrat, koriste se mnogo češće od velikih. Stoga definiramo niz velikih slova u CP1251 kao KOI8-R.
Pokušajmo to učiniti bez obzira na velika i mala slova ("spektra" bez obzira na velika i mala slova)

1) $str = "Ruski tekst";
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 = "NIZ VELIKIM SLOVIMA RUSKI TEKST";
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

Kao što vidite, ispravno kodiranje dosljedno vodi s "spektrima" koji razlikuju velika i mala slova (ako redak sadrži mali broj velika slova), i s razlikovanjem velikih i malih slova. U drugom slučaju, s onima koji nisu osjetljivi na velika i mala slova, vodstvo nije tako pouzdano, naravno, ali prilično stabilno čak i na malim linijama. Također se možete poigrati s težinama slova - učiniti ih nelinearnim u odnosu na frekvenciju, na primjer.

5. Zaključak

Tema ne pokriva rad s UTF-8 - ovdje nema fundamentalne razlike, osim što će dobivanje znakovnih kodova i dijeljenje niza na znakove biti nešto duže/složenije.
Ove ideje mogu se proširiti ne samo na ćirilično kodiranje, naravno - pitanje je samo u “spektru” odgovarajućih jezika/kodiranja.

p.s. Ako je stvarno potrebno/zanimljivo, postavit ću drugi dio potpuno radne biblioteke na GitHub. Iako vjerujem da su podaci u postu sasvim dovoljni za brzo pisanje takve biblioteke koja odgovara vašim potrebama - "spektar" za ruski jezik je postavljen, lako se može prenijeti na sva potrebna kodiranja.

Čitam puno tekstova s ​​različitih RSS feedova i ubacujem ih u svoju bazu podataka.

Naravno, postoji nekoliko različitih kodiranja znakova koji se koriste u cijevima, npr. UTF-8 i ISO-8859-1.

Nažalost, ponekad se javljaju problemi s kodiranjem teksta. Primjer:

1) "ß" u "Fußball" trebao bi izgledati ovako u mojoj bazi podataka: "Ÿ". Ako je "Ÿ", prikazano je ispravno.

2) Ponekad "ß" u "Fußball" izgleda ovako u mojoj bazi podataka: "ß". Tada se, naravno, neispravno prikazuje.

3) U ostalim slučajevima, "ß" se pohranjuje kao "ß" - dakle bez ikakvih promjena. Tada se također neispravno prikazuje.

Što mogu učiniti da izbjegnem slučajeve 2 i 3?

Kako mogu sve učiniti istim kodiranjem, po mogućnosti UTF-8? Kada trebam koristiti utf8_encode(), kada trebam koristiti utf8_decode() (jasno je koji je učinak, ali kada trebam koristiti funkcije?), i kada trebam učiniti bilo što s unosom?

Možete li mi pomoći i reći mi kako napraviti sve isto kodiranje? Možda s funkcijom mb-detect-encoding()? Mogu li napisati funkciju za ovo? Dakle, moji problemi su: 1) Kako saznati koje se kodiranje koristi u tekstu 2) Kako ga pretvoriti u UTF-8 - bez obzira na staro kodiranje

UREDI: Hoće li ova značajka raditi?

Funkcija correct_encoding($text) ( $current_encoding = mb_detect_encoding($text, "auto"); $text = iconv($current_encoding, "UTF-8", $text); return $text; )

Testirao sam ga, ali ne radi. Što ne valja s njim?

24 odgovora

Ako primijenite utf8_encode() na već postojeći UTF8 niz, vratit će iskrivljeni UTF8 izlaz.

Napravio sam funkciju koja rješava sve te probleme. Zove se Encoding::toUTF8().

Ne morate znati kakvo je kodiranje vaših nizova. To može biti Latin1 (iso 8859-1), Windows-1252 ili UTF8 ili ih niz može sadržavati. Encoding::toUTF8() pretvara sve u UTF8.

Učinio sam to jer mi je servis davao tok podataka, sve zbrkane, miješajući UTF8 i Latin1 u jednom retku.

Upotreba:

Require_once("Encoding.php"); koristiti \ForceUTF8\Encoding; // Sada je u prostoru imena. $utf8_string = Kodiranje::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Kodiranje::toLatin1($utf8_or_latin1_or_mixed_string);

Uključio sam još jednu funkciju, Encoding::fixUFT8(), koja će popraviti svaki UTF8 niz koji izgleda iskrivljeno.

Upotreba:

Require_once("Encoding.php"); koristiti \ForceUTF8\Encoding; // Sada je u prostoru imena. $utf8_string = Kodiranje::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

Ažuriranje: Konvertirao sam funkciju (forceUTF8) u obitelj statičkih funkcija u klasi Encoding. Nova značajka- Kodiranje::toUTF8().

Prvo morate odrediti koje je kodiranje korišteno. Budući da analizirate RSS feedove (moguće preko HTTP-a), trebali biste pročitati kodiranje iz parametra skupa znakova polja Content-Type HTTP zaglavlja. Ako nedostaje, pročitajte kodiranje iz atributa kodiranja instrukcije za obradu. Ako i ovo nedostaje, koristite UTF-8 kako je definirano u specifikaciji.

Promijeniti Evo što ću vjerojatno učiniti:

Teško je detektirati kodiranje.

mb_detect_encoding radi pogađanjem na temelju više kandidata koje proslijedite. U nekim kodiranjima, određeni nizovi bajtova nisu valjani, tako da može razlikovati različite kandidate. Nažalost, postoji mnogo kodiranja u kojima su isti bajtovi valjani (ali različiti). U tim je slučajevima nemoguće odrediti kodiranje; Možete primijeniti vlastitu logiku da nagađate u tim slučajevima. Na primjer, podaci koji dolaze s japanske stranice najvjerojatnije će biti u japanskom kodiranju.

Dok se bavite samo zapadnoeuropskim jezicima, pogledajmo tri glavna kodiranja: utf-8, iso-8859-1 i cp-1252. Budući da su ovo zadane vrijednosti za mnoge platforme, vjerojatno će biti i pogrešno prijavljene. Na primjer. ako ljudi koriste drugačija kodiranja, vjerojatno će biti otvoreni u vezi s tim, jer inače njihov softver vrlo često će se pokvariti. Dakle, dobra strategija je vjerovati davatelju osim ako kodiranje nije deklarirano kao jedno od ova tri. Svejedno biste trebali udvostručiti da je stvarno valjan koristeći mb_check_encoding (imajte na umu da valjano nije isto što jest - isti unos može biti valjan za mnoga kodiranja). Ako je jedan od njih, možete koristiti mb_detect_encoding da ih razlikujete. Srećom, ovo je prilično determinističko; Samo trebate upotrijebiti ispravnu sekvencu otkrivanja, a to je UTF-8,ISO-8859-1,WINDOWS-1252.

Nakon što ste otkrili kodiranje, trebate ga pretvoriti u interni prikaz (utf-8 je jedini razuman izbor). Funkcija utf8_encode pretvara iso-8859-1 u utf-8 tako da se može koristiti samo za tu specifičnu vrstu unosa. Za druga kodiranja koristite mb_convert_encoding.

Ova varalica navodi neka uobičajena upozorenja povezana s rukovanjem UTF-8 u PHP-u: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Ova funkcija, koja otkriva višebajtne znakove u nizu, također može biti korisna ():

Funkcija detectUTF8($string) ( return preg_match("%(?: [\xC2-\xDF][\x80-\xBF] # ne-predugačak 2-bajt |\xE0[\xA0-\xBF][\x80- \xBF] # isključujući prekoračenja |[\xE1-\xEC\xEE\xEF][\x80-\xBF](2) # ravno 3-bajta |\xED[\x80-\x9F][\x80-\xBF] # isključujući surogate |\xF0[\x90-\xBF][\x80-\xBF](2) # ravnine 1-3 |[\xF1-\xF3][\x80-\xBF](3) # ravnine 4- 15 |\xF4[\x80-\x8F][\x80-\xBF](2) # ravnina 16)+%xs", $string); )

Malo upozorenja, rekli ste da bi se "ß" trebalo pojaviti kao "Ÿ" u vašoj bazi podataka.

To je vjerojatno zbog činjenice da koristite bazu podataka s kodiranjem znakova latin1 ili možda veza php-mysql nije ispravno konfigurirana, php pretpostavlja da je vaš mysql konfiguriran za korištenje utf-8 pa šalje podatke kao utf8, ali vaš mysql vjeruje da php šalje podatke kodirane kao iso-8859-1, pa može pokušati ponovno kodirati vaše poslane podatke kao utf-8, uzrokujući ovakve probleme.

Pogledaj ovo, moglo bi ti pomoći: http://php.net/manual/en/function.mysql-set-charset.php

Morate provjeriti kodiranje na ulazu jer odgovori mogu biti kodirani različitim kodiranjem.
Prisiljavam da se sav sadržaj šalje u UTF-8 otkrivanjem i prijevodom pomoću sljedeće funkcije:

Funkcija 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) nastavi; if (strcasecmp($encoding, "UTF-8") != 0) ( $encoding = iconv($encoding, " UTF-8", $var[ $key ]); if ($encoding === false) continue; $var[ $key ] = $encoding; ) ) ) )

Ovaj postupak će sve okrenuti PHP varijable, koji dolaze s udaljenog glavnog računala u UTF-8.
Ili zanemarite vrijednost ako se kodiranje ne može otkriti ili pretvoriti.
Možete ga prilagoditi svojim potrebama.
Jednostavno ga pozovite prije korištenja varijabli.

Vaše kodiranje izgleda kao da ste kodirani u UTF-8 dvaput; odnosno iz nekog drugog kodiranja u UTF-8 i opet u UTF-8. To je kao da ste iso-8859-1 pretvorili iz iso-8859-1 u utf-8 i tretirali s novim retkom kao iso-8859-1 za drugu konverziju u UTF-8.

Evo nekih pseudokoda za ono što ste učinili:

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

Morate probati:

  • otkrijte kodiranje koristeći mb_detect_encoding() ili što god želite koristiti
  • ako je UTF-8, pretvorite u iso-8859-1 i ponovite korak 1
  • konačno pretvoriti natrag u UTF-8

Pretpostavlja se da ste u "prosječnoj" konverziji koristili iso-8859-1. Ako ste koristili windows-1252, pretvorite u windows-1252 (latin1). Izvorno kodiranje izvora nije važno; onaj koji ste koristili u pogrešnoj, drugoj pretvorbi.

Ovo je moja pretpostavka što se dogodilo; možete učiniti malo više da dobijete četiri bajta umjesto jednog proširenog ASCII bajta.

Njemački također koristi iso-8859-2 i windows-1250 (latin2).

Dizajniranje kodiranja znakova RSS feedova izgleda komplicirano. Čak i obične web stranice često izostavljaju ili lažu o svom kodiranju.

Dakle, možete pokušati koristiti ispravan način za otkrivanje kodiranja, a zatim se vratiti na neki oblik automatskog otkrivanja (pogađanja).

Znam da je ovo staro pitanje, ali vjerujem da koristan odgovor nikada ne škodi. Imam problema s kodiranjem između desktop aplikacija, SQLite i GET/POST varijabli. Neki od njih će biti u UTF-8, neki će biti u ASCII, a uglavnom će stvari biti zbunjujuće kada su uključeni strani znakovi.

Evo mog rješenja. Izglađuje vaš GET/POST/REQUEST (promašio sam kolačići, ali ih možete dodati ako je potrebno) pri svakom učitavanju stranice prije obrade. Dobro radi u zaglavlju. PHP će izdati upozorenja ako ne može automatski odrediti izvorno kodiranje, tako da su ta upozorenja potisnuta pomoću @.

//Pretvorite sve u našim varijantama u UTF-8 za dobru igru ​​s bazom podataka... //Upotrijebite nešto automatskog otkrivanja ovdje da nam pomogne da ne kodiramo dvostruko... //Suzmite moguća upozorenja sa @ za slučajeve kada se kodiranje ne može otkriti pokušaj ( $process = array(&$_GET, &$_POST, &$_REQUEST); while (list($key, $val) = each($process)) ( foreach ($val as $k => $v) ( poništi($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")]; ) else ( $process[$key][@mb_convert_encoding($k,"UTF- 8","auto")] = @mb_convert_encoding($v,"UTF-8","auto"); ) ) ) poništi($proces); ) catch(Iznimka $ex)()

Provjeravao sam rješenja kodiranja s AGES-om i ova je stranica vjerojatno kraj godina traženja! Provjerio sam neke od prijedloga koje ste spomenuli i evo mojih bilješki:

Ovo je moj testni redak:

ovo je redak "wròng wrìtten" za koji se nisam koristio posebne postavke chars to see thèm, pretvoreno pomoću fùnctìon!! Pa što je ovo!

Font moje stranice je UTF-8

Ako učinim INSERT na ovaj način, imam neke znakove u svojoj bazi podataka koji vjerojatno dolaze s Marsa... pa ih moram pretvoriti u "osjetljivi" UTF-8. Pokušao sam utf8_encode(), ali su vanzemaljski znakovi još uvijek napadali moju bazu podataka...

Dakle, pokušao sam koristiti funkciju forceUTF8 koja se nalazi na broju 8, ali u DB-u spremljeni niz izgleda ovako:

ovo je "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!! Pa što je ovo!

Dakle, prikupljanjem još nekih informacija na ovoj stranici i kombiniranjem s ostalim informacijama na drugim stranicama, riješio sam problem ovim rješenjem:

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

Sada u svojoj bazi podataka imam niz s ispravnim kodiranjem.

Bilješka: Samo napomena da vodite računa o funkciji mysql_client_encoding! Morate biti povezani s bazom podataka jer ova funkcija zahtijeva ID resursa kao parametar.

Ali ok, ovo ponovno kodiranje radim prije svog INSERT-a, tako da mi to nije problem.

Nadam se da će ovo pomoći nekome kao što je ova stranica pomogla meni!

Hvala svima!

Zanimljiva stvar kod mb_detect_encoding i mb_convert_encoding je da je bitan redoslijed kodiranja koje nudite:

// $input je zapravo UTF-8 mb_detect_encoding($input, "UTF-8", "ISO-8859-9, UTF-8"); // ISO-8859-9 (POGREŠNO!) mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9"); // UTF-8 (OK)

Na ovaj način možete koristiti određeni redoslijed kada specificirate očekivana kodiranja. Međutim, imajte na umu da ovo nije sigurno.

Echo mb_detect_encoding($str, "auto");

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

Ne znam stvarno kakvi su rezultati, ali predlažem da samo uzmete neke svoje kanale s različitim kodiranjem i isprobate radi li mb_detect_encoding ili ne.

Ažuriraj
auto je skraćenica za "ASCII, JIS, UTF-8, EUC-JP, SJIS". vraća otkriveno kodiranje, koje možete koristiti za pretvaranje niza u utf-8 pomoću iconv.

Nisam ga testirao, tako da nema garancija. a možda postoji i lakši način.

Ova verzija je za njemački jezik, ali možete mijenjati $CHARSETS i $TESTCHARS

Class CharsetDetector ( privatni statički $CHARSETS = array("ISO_8859-1", "ISO_8859-15", "CP850"); privatni statički $TESTCHARS = array("€", "ä", "Ä", "ö", "Ö", "ü", "Ü", "ß"); javna statička funkcija convert($string) ( return self::__iconv($string, self::getCharset($string)); ) javna statička funkcija getCharset ($string) ( $normalized = self::__normalize($string); if(!strlen($normalized))return "UTF-8"; $best = "UTF-8"; $charcountbest = 0; foreach (self ::$CHARSETS kao $charset) ( $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=$charset; ) //echo $text."
"; ) vrati $best; ) privatna statička funkcija __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; else $ret .=$str[$i]; if (($i + $bytes) > $len) $ret .=$str[$i]; $ret2=$str [$i]; while ($bytes > 1) ( $i++; $b = ord($str[$i]); if ($b< 128 || $b >191) ($ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;) else $ret2.=$str[$i]; $bajtova--; ) ) ) return $ret; ) privatna statička funkcija __iconv($string, $charset) ( return iconv ($charset, "UTF-8", $string); ) )

Nakon sortiranja vaših php skripti, ne zaboravite reći mysql-u koje kodiranje prosljeđujete i želite li ga primiti.

Primjer: postavljanje skupa znakova na utf8

Prosljeđivanje utf8 podataka latin1 tablici u latin1 I/O sesiji daje ovim gadnim pticama perje. To vidim svaki dan u maloprodajnim trgovinama. Naprijed i natrag može se činiti da je točno. Ali phpmyadmin će pokazati istinu. Recite mysql-u koje kodiranje prosljeđujete da će obraditi mysql podaci za tebe.

Kako oporaviti postojeće mysql kodirane podatke je drugo pitanje za raspravu. :)

Postoji problem: kako brzo odrediti kodiranje tekstualni niz u odnosu na UTF-8. Sve češće moramo raditi s nizovima u UNICODE kodiranju.

Ispod je funkcija za provjeru treba li UNICODE (UTF-8) kodiranje pretvoriti u WINDOWS (win-1251) kodiranje

Funkcija daje prilično točan odgovor, iako se ne temelji na pretvorbi znak-po-kod.

funkcija detect_my_utf($s)( $s=urlencode($s); // u nekim slučajevima - nepotrebna operacija (komentirajte) $res="0"; $j=strlen($s); $s2=strtoupper($ s) ; $s2=str_replace("%D0","",$s2); $s2=str_replace("%D1","",$s2); $k=strlen($s2); $m=1 ; if ($k>0)( $m=$j/$k; if (($m>1.2)&&($m

Kratak opis funkcije detektiraj_moj_utf():

  • pretvoriti (string u poseban format)
  • izračunajte duljinu dolaznog niza
  • velika slova u nizu
  • uklonite određene kodove %D0 i %D1
  • izračunajte duljinu nova linija
  • dobivamo omjer stare linije prema novoj

Ako je taj omjer 1 ili mu je blizu, tada se sumnja da dolazni niz nije bio kodiran u UNICODE. Ako je ovaj omjer u rasponu od 1,2 do 2,2, tada možete sigurno rekodirati niz u WINDOWS win-1251 kodiranje.

Izlaz funkcije je 0 odnosno 1, a ne UNICODE ili UNICODE.

Primjeri izvršavanja funkcija:

Dolazna linija: Rí̈R?S?S?R?R?Rê S?R?R·R?R°R?RëS? R°R?RëR?R°S+RëRë R? imageready Konvertirani niz: %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 Rezultat funkcije: 1 Kodirana fraza: redoslijed stvaranja animacije u imagereadyju

Dolazni niz: R?S?R?R?R?S

Dolazni niz: Rí̈S?R?R?S?R°R?R?R° S+S"RčR?RëS? Rí̈R?S+R°S?R°Rí̈R°R?R?S

Ulazni niz: vodič za crtanje Pretvoreni niz: %EF%EE%F1%EE%E1%E8%E5 %EF%EE %F0%E8%F1%EE%E2%E0%ED%E8%FE Rezultat funkcije: 0 Kodirana fraza : vodič za crtanje Ovaj algoritam dobro se nosi s različitim dolaznim nizovima kao dijelom usluge statistike pretvorbe tražilice.

Zanimljivi materijali na web mjestu:

  • Članak o interesu tražilice stranice. Možda su neki od materijala već zastarjeli nakon 10 godina, ali na neke točke vrijedi obratiti pozornost.

  • Vaš pogled na problem razmjene hiperveza između stranica donatora i stranica primatelja.

  • Još jedan life hack. Pobijedili smo nepoštene igrače u igrici “Balda”. Velika baza riječi koja se lako može proširiti.

Naišao sam na problem - automatsko otkrivanje stranice/teksta/bilo kojeg kodiranja. Zadatak nije nov, a mnogi bicikli su već izumljeni. Članak sadrži kratak pregled onoga što je pronađeno na internetu - plus prijedlog onoga što mislim da je vrijedno rješenje.

1. Zašto ne mb_detect_encoding()?

Ukratko, ne ide.

Gledajmo:
// Na ulazu - ruski tekst u CP1251 koji kodira $string = iconv("UTF-8", "Windows-1251", "Prišao je Ani Pavlovnoj, poljubio joj ruku, otkrivajući joj svoju namirisanu i blistavu ćelavu glavu, i mirno sjeo na sofu."); // Da vidimo što nam md_detect_encoding() daje. Prvo $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 // Sada $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
Kao što vidite, rezultat je potpuni nered. Što radimo kada nije jasno zašto se neka funkcija tako ponaša? Tako je, proguglajmo. Našao sam odličan odgovor.

Kako biste konačno raspršili sve nade za korištenje mb_detect_encoding(), morate pogledati izvorni kod ekstenzije mbstring. Dakle, zasučite rukave i idemo:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // linija 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + klik:
// ext/mbstring/libmbfl/mbfl/mbfilter.c: 643 const char *mbfl_identify_encoding_name (mbfl_string *string, enum mbfl_no_encoding *elist, incint, strict) (const mbfl_encoding; , strog); ...
Ctrl + klik:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * identificiraj kodiranje */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Neću objaviti cijeli tekst metode, kako ne bih zatrpao članak nepotrebnim izvorima. Zainteresirani će sami pogledati. Zanima nas linija broj 593, gdje zapravo provjeravamo odgovara li znak kodiranju:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_function)(*p, filter); ako (filter->zastavica) (loš++;)
Evo glavnih filtera za jednobajtnu ćirilicu:

Windows-1251 (izvorni komentari sačuvani)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* sve je ovo sada tako ružno! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filter) ( if (c >= 0x80 && c< 0xff) filter->zastava = 0; inače filter->

KOI8-R
// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filter) ( if (c >= 0x80 && c< 0xff) filter->zastava = 0; inače filter->zastavica = 1; /* nije to */ return c; )

ISO-8859-5 (ovdje je sve zabavno)
// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter) ( return c; )
Kao što vidite, ISO-8859-5 uvijek vraća TRUE (za vraćanje FALSE, trebate postaviti filter->flag = 1).

Kad smo pogledali filtere, sve je sjelo na svoje mjesto. Ne postoji način da se razlikuje CP1251 od KOI8-R. Općenito, ISO-8859-5, ako je na popisu kodiranja, uvijek će biti otkriven kao točan.

Općenito, neuspjeh. To je razumljivo - općenito je nemoguće saznati kodiranje samo pomoću kodova znakova, budući da se ti kodovi sijeku u različitim kodovima.

2. Što Google donosi

A Google donosi svakakve bedarije. Ovdje neću ni postavljati izvor, pogledajte sami ako želite (maknite razmak nakon http://, ne znam kako prikazati tekst bez linka):

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

3. Pretraživanje po čvorištu

1) opet kodovi znakova: habrahabr.ru/blogs/php/27378/#comment_710532

2) po mom mišljenju, vrlo zanimljivo rješenje: habrahabr.ru/blogs/php/27378/#comment_1399654
Za i protiv u komentaru na poveznici. Osobno mislim da je ovo rješenje suvišno samo za detekciju kodiranja - ispada da je previše moćno. Definiranje kodiranja u njemu je nuspojava).

4. Zapravo, moja odluka

Ideja je nastala prilikom pregledavanja drugog linka iz prethodnog odjeljka. Ideja je sljedeća: uzmemo veliki ruski tekst, izmjerimo frekvencije različitih slova i pomoću tih frekvencija detektiramo kodiranje. Gledajući unaprijed, odmah ću reći da će biti problema s velikim i malim slovima. Stoga objavljujem primjere učestalosti slova (nazovimo to "spektar"), i velikih i malih slova (u drugom slučaju sam malom slovu iste frekvencije dodao još veće i uklonio sve one veće). U tim "spektrima" sva su slova s ​​frekvencijama manjim od 0,001 i razmakom izrezana. Ovo sam dobio nakon obrade "Rata i mira":

"Spektar" koji razlikuje velika i mala slova:
niz ("o" => 0,095249209893009, "e" => 0,06836817536026, "a" => 0,067481298384992, "i" => 0,055995027400041, "n" => 0,052242744063325, ... . "e" => 0,002252892226507, "N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "B" => 0,0014044332975731, "O" => 0,0013188987793209 , "A" => 0,0012623590130186, "K" => 0,0011804488387602, "M" => 0,001061932790165,)

Neosjetljivo na velika i mala slova:
niz ("O" => 0,095249209893009, "o" => 0,095249209893009, "E" => 0,06836817536026, "e" => 0,06836817536026, "A" => 0,067481298384992, " a " => 0,067481298384992, "I" => 0,055995027400041 , "i" => 0,055995027400041, .... "C" => 0,0029893589260344, "c" => 0,0029893589260344, "c" => 0,0024649163501406, "c" => 0,00246491635 01406, "E" => 0,002252892226507, "e " => 0,002252892226507, "F" => 0,0015961610948418, "f" => 0,0015961610948418,)

Spektri u različitim kodovima (ključevi polja su kodovi odgovarajućih znakova u odgovarajućem kodiranju):

Unaprijediti. Uzimamo tekst nepoznatog kodiranja, za svako kodiranje koje se provjerava nalazimo učestalost trenutnog znaka i dodajemo ga "ocjeni" ovog kodiranja. Kodiranje s najvišom ocjenom najvjerojatnije je kodiranje teksta.

$encodings = array("cp1251" => zahtijevaju "specter_cp1251.php", "koi8r" => zahtijevaju "specter_koi8r.php", "iso88595" => zahtijevaju "specter_iso88595.php"); $enc_rates = array(); za ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)]; ) ) var_dump($enc_rates);
Nemojte ni pokušavati sami pokrenuti ovaj kôd - neće uspjeti. Možete uzeti u obzir ovaj pseudokod - izostavio sam detalje kako ne bih zatrpao članak. $char_specter su upravo oni nizovi koji su navedeni u pastebinu.

rezultate
Redovi tablice su kodiranje teksta, stupci su sadržaj niza $enc_rates.

1) $str = "Ruski tekst";
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

Sve je u redu. Pravo kodiranje već ima 4 puta veću ocjenu od ostalih - ovo je za tako kratak tekst. Za duže tekstove omjer će biti približno isti.


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

Ups! Potpuni nered. To je zato što velika slova u CP1251 obično odgovaraju malim u KOI8-R. A mala slova, zauzvrat, koriste se mnogo češće od velikih. Stoga definiramo niz velikih slova u CP1251 kao KOI8-R.
Pokušajmo to učiniti bez obzira na velika i mala slova ("spektra" bez obzira na velika i mala slova)

1) $str = "Ruski tekst";
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 = "NIZ VELIKIM SLOVIMA RUSKI TEKST";
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

Kao što vidite, ispravno kodiranje dosljedno vodi i kod "spektra" koji razlikuju velika i mala slova (ako redak sadrži mali broj velikih slova) i kod onih koji nisu osjetljivi na velika i mala slova. U drugom slučaju, s onima koji nisu osjetljivi na velika i mala slova, vodstvo nije tako pouzdano, naravno, ali prilično stabilno čak i na malim linijama. Također se možete poigrati s težinama slova - učiniti ih nelinearnim u odnosu na frekvenciju, na primjer.

5. Zaključak

Tema ne pokriva rad s UTF-8 - ovdje nema fundamentalne razlike, osim što će dobivanje znakovnih kodova i dijeljenje niza na znakove biti nešto duže/složenije.
Ove ideje mogu se proširiti ne samo na ćirilično kodiranje, naravno - pitanje je samo u “spektru” odgovarajućih jezika/kodiranja.

p.s. Ako je stvarno potrebno/zanimljivo, postavit ću drugi dio potpuno radne biblioteke na GitHub. Iako vjerujem da su podaci u postu sasvim dovoljni za brzo pisanje takve biblioteke koja odgovara vašim potrebama - "spektar" za ruski jezik je postavljen, lako se može prenijeti na sva potrebna kodiranja.

Ideja - Lutrija

Nisam došao na ideju da dobijem kodiranje, ali nažalost, ne mogu vam sada reći autora, jer je to bilo prije otprilike 4 godine, a odakle sam dobio ove informacije odavno je zaboravljeno. Autor je predložio definiciju i pokazao primjer za 1-2 kodiranja u Pythonu. Jednostavnost njegovog rješenja nije me ostavila po strani te sam ga razvio do željenog rezultata.
Bit ideje leži u samim kodnim tablicama kodiranja. Kao što znate, svako kodiranje sadrži vlastitu tablicu kodova i svakom znaku kodiranja dodijeljena je određena vrijednost. Ovdje neću prikazati tablice kodiranja; sada ih je prilično lako pronaći na Internetu.
Princip implementacije je sljedeći:
  1. Stvara se varijabla niza za pohranjivanje rezultata "analize" provjerenog teksta. Svaki element niza sadržavat će rezultat za određeno kodiranje.
  2. Tekst primljen kao ulaz u funkciju se ponavlja simbolički.
  3. Redni broj (značenje tog znaka) uzima se iz svakog znaka i uspoređuje s rasponom kodiranja.
  4. Ako vrijednost pada na veliko slovo (veliko) znak, vrijednost 1 dodaje se elementu polja koji pohranjuje rezultat ovog kodiranja.
  5. Ako vrijednost pada na mali (mali) znak, vrijednost 3 dodaje se elementu polja koji pohranjuje rezultat ovog kodiranja.
  6. To kodiranje, točnije element niza koji pohranjuje rezultat svog kodiranja, koji je osvojio najviše bodova, najvjerojatnije je originalno kodiranje.
Ovaj algoritam vrijedi za jednobajtno kodiranje kao što su KOI-8, CP1251 (windows-1251) i drugi. Međutim, za dvobajtno kodiranje (UTF-8 u mom slučaju), ovaj pristup će proizvesti pogrešan rezultat. Za početak, pokušao sam riješiti ovaj problem tako što sam za velika slova dodao 5, a za mala slova 7. Rezultat je postao bolji, ali greške u prepoznavanju su i dalje prisutne. Nakon malo eksperimentiranja, zaključio sam da za ispravno određivanje UTF-a, za velika slova rezultatu treba dodati 10, za mala slova 14, odnosno 2 puta više od moje početne pretpostavke. Međutim, za bolje vizualno razumijevanje koda, ostavio sam 5 odnosno 7 za UTF znakove, a tijekom testiranja povećao sam te vrijednosti za 2 i dodao ih rezultatu.
To je u biti cijeli algoritam. I to bez ikakvih nepotrebnih muka.
Najviše vremena koje sam potrošio na implementaciju ove funkcije bilo je, naravno, traženje tablica kodova i ispravnog rasporeda raspona. Ne samo da je bilo prilično teško pronaći trenutnu tablicu kodova u vrijeme kada sam prvi put napisao ovu funkciju, već rasponi znakova u njima nasumično skaču. Međutim, tada sam se odlučio za najaktualnija (i dan danas) kodiranja: UTF-8, CP1251, KOI8-R, IBM866, ISO-8859-5 i MAC. Ako vam ova kodiranja nisu dovoljna, možete na temelju ovog algoritma dodati kod.

Od riječi do prakse

Zapravo, cijeli kod funkcije u Pythonu izgleda ovako:

Kodiranja = ( "UTF-8": "utf-8", "CP1251": "windows-1251", "KOI8-R": "koi8-r", "IBM866": "ibm866", "ISO-8859- 5": "iso-8859-5", "MAC": "mac", ) """ Određivanje kodiranja teksta """ def get_codepage(str = None): velika slova = 1 mala slova = 3 utfupper = 5 utflower = 7 codepages = () za enc u encodings.keys(): codepages = 0 ako str nije None i len(str) > 0: last_simb = 0 za simb u str: simb_ord = ord(simb) """neruski znakovi " "" ako simb_ord< 128 or simb_ord >256: nastavak """UTF-8""" if 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 = codepages idx = item return idx
Primjer poziva funkcije

Ispis kodiranja

Što je s PHP-om?

Prepisivanje gotove funkcije iz Pythona u PHP nije bilo teško. Izgledom se praktički ne razlikuje od svog roditelja u Pythonu:

/** * Odredite kodiranje teksta * @param String $text Text * @return String Kodiranje teksta */ function get_codepage($text = "") ( if (!empty($text)) ( $utflower = 7; $utfupper = 5; $lowercase = 3; $uppercase = 1; $last_simb = 0; $charsets = array("UTF-8" => 0, "CP1251" => 0, "KOI8-R" => 0, "IBM866 " => 0, "ISO-8859-5" => 0, "MAC" => 0,); za ($a = 0; $a< strlen($text); $a++) { $char = ord($text[$a]); // non-russian characters if ($char<128 || $char>256) nastaviti; // UTF-8 if (($last_simb==208) && (($char>143 && $char<176) || $char==129)) $charsets["UTF-8"] += ($utfupper * 2); if ((($last_simb==208) && (($char>175 && $char<192) || $char==145)) || ($last_simb==209 && $char>127 && $char<144)) $charsets["UTF-8"] += ($utflower * 2); // CP1251 if (($char>223 && $char<256) || $char==184) $charsets["CP1251"] += $lowercase; if (($char>191 && $char<224) || $char==168) $charsets["CP1251"] += $uppercase; // KOI8-R if (($char>191 && $char<224) || $char==163) $charsets["KOI8-R"] += $lowercase; if (($char>222 && $char<256) || $char==179) $charsets["KOI8-R"] += $uppercase; // IBM866 if (($char>159 && $char<176) || ($char>223 && $char<241)) $charsets["IBM866"] += $lowercase; if (($char>127 && $char<160) || $char==241) $charsets["IBM866"] += $uppercase; // ISO-8859-5 if (($char>207 && $char<240) || $char==161) $charsets["ISO-8859-5"] += $lowercase; if (($char>175 && $char<208) || $char==241) $charsets["ISO-8859-5"] += $uppercase; // MAC if ($char>221 && $char<255) $charsets["MAC"] += $lowercase; if ($char>127 && $char<160) $charsets["MAC"] += $uppercase; $last_simb = $char; } arsort($charsets); return key($charsets); } }
Primjer poziva funkcije

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

LikBez, ili Ne ometajte rad stroja

Ne biste trebali pokušavati testirati pad ove funkcije. Iz algoritma je jasno da što manje teksta primi kao ulaz, to je veća vjerojatnost da će funkcija prepoznati netočno kodiranje. S druge strane, hranjenje volumena Lava Tolstoja također nema smisla: ova se metoda dobro nosi s malom rečenicom od 100-200 znakova. I premda sam u primjerima poziva na ulaz poslao cijeli sadržaj određene datoteke “test.txt”, koja je trebala sadržavati tekst čije kodiranje treba odrediti, mali dio teksta može (i treba) biti proslijeđen na ulaz funkcije.
Smatram da perverzije s miješanjem velikih i malih slova općenito nisu prikladne u ovom slučaju, budući da je ova metoda napisana za običan, uobičajen zadatak s približno pismenim ruskim jezikom. A takvi me eksperimenti najčešće podsjećaju na vic:

Ruska tvornica za preradu drva kupila je japansku jedinicu. Ruski radnici su se okupili oko njega i shvatili smo kako radi. Jedan je uzeo dasku i zabio je u nju. Jedinica:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz... Na izlazu gotov tabure. Dečki: Wow!!! Jedinica na zaslonu: dobro, što ste mislili? Drugi je uzeo neobrađeni balvan i ubacio ga u jedinicu. Unit:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzof its... The output is a finished carved sideboard. Dečki: Wow!!! Jedinica na zaslonu: dobro, što ste mislili? Treći čovjek nije izdržao, odnekud je izvukao šinu i zabio je u jedinicu. Jedinica: drrrrrrr-tyh-tyh-tyh... Počelo se dimiti i na displeju piše: Wow!!! Dečki: pa što ste mislili!!!
Dakle, za takve uvrnute testove najvjerojatnije će vam trebati uvrnuti algoritam, što ova funkcija nije. A iz prakse ću reći da me tijekom moje uporabe 4 godine ova metoda nikada nije iznevjerila i uvijek je dala pravi rezultat.
Nadam se da će moj članak nekome biti od koristi.
Hvala vam na pažnji.

Prilikom korištenja cijelog ili dijela sadržaja ne zaboravite navesti link na izvor, odnosno na moj blog.