Php kodlaşdırma xəritəsini necə tapmaq olar. PHP-də mətn kodlaşdırmasının müəyyən edilməsi - mövcud həllərin icmalı və daha bir velosiped. Google nə gətirir

Bir problemlə qarşılaşdım - səhifənin/mətnin/hər hansı kodlaşdırmanın avtomatik aşkarlanması. Tapşırıq yeni deyil və bir çox velosipedlər artıq icad edilmişdir. Məqalədə İnternetdə tapılanların qısa icmalı var - üstəlik, layiqli bir həll olduğunu düşündüyüm bir təklif.

1. Niyə mb_detect_encoding() deyil?

Bir sözlə, işləmir.

Baxaq:
// Girişdə - CP1251 kodlu rusca mətn $string = iconv("UTF-8", "Windows-1251", "O, Anna Pavlovnaya yaxınlaşdı, onun əlini öpdü, ətirli və parıldayan keçəl başını ona göstərdi və sakitcə oturdu. divanda aşağı."); // Gəlin görək md_detect_encoding() bizə nə verir. Birinci $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 // İndi $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
Gördüyünüz kimi, çıxış tam bir qarışıqlıqdır. Bir funksiyanın niyə belə davrandığı aydın olmayanda nə edirik? Düzdü, Google-da axtaraq. Əla cavab tapdım.

Nəhayət, mb_detect_encoding() istifadəsinə dair bütün ümidləri aradan qaldırmaq üçün mbstring genişləndirilməsinin mənbə koduna baxmaq lazımdır. Beləliklə, qollarınızı yuxarı çəkin və gedək:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // sətir 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + klikləyin:
// 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; elflists (kodlaşdırma; elflists, encoding = , sərt);
Ctrl + klikləyin:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * kodlaşdırmanı müəyyənləşdirin */ const mbfl_encoding * mbfl_identify_encoding (mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Məqaləni lazımsız mənbələrlə qarışdırmamaq üçün metodun tam mətnini yerləşdirməyəcəyəm. Maraqlananlar özlərinə baxacaqlar. Bizi 593 nömrəli sətir maraqlandırır, burada simvolun kodlaşdırmaya uyğun olub olmadığını yoxlayırıq:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_funksiya)(*p, filter); if (filtr->bayraq) (pis++; )
Bir baytlıq kiril üçün əsas filtrlər bunlardır:

Windows-1251 (orijinal şərhlər qorunur)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* bütün bunlar indi çox çirkindir! */ statik int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filtr) ( əgər (c >= 0x80 && c)< 0xff) filter->bayraq = 0;

başqa filtr->
KOI8-R< 0xff) filter->// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 statik int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filtr) ( əgər (c >= 0x80 && c)

bayraq = 0;
else filter->bayraq = 1; /* deyil */ qaytarmaq c; )
ISO-8859-5 (burada hər şey əyləncəlidir)

// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true (int c, mbfl_identify_filter *filtr) ( qaytarın c; )

Gördüyünüz kimi, ISO-8859-5 həmişə TRUE qaytarır (FALSE qaytarmaq üçün filter->bayraq = 1 təyin etməlisiniz).

Filtrlərə baxanda hər şey öz yerinə düşdü. CP1251-i KOI8-R-dən ayırmaq üçün heç bir yol yoxdur. Ümumiyyətlə, ISO-8859-5, əgər kodlaşdırma siyahısındadırsa, həmişə düzgün olaraq aşkar ediləcəkdir.

Ümumiyyətlə, uğursuz. Bu başa düşüləndir - ümumiyyətlə, kodlaşdırmanı yalnız simvol kodları ilə tapmaq mümkün deyil, çünki bu kodlar müxtəlif kodlaşdırmalarda kəsişir.

2. Google nələri gündəmə gətirir
Google isə hər cür alçaqlığı gündəmə gətirir. Mənbəni də bura yerləşdirməyəcəyəm, istəsəniz özünüzə baxın (http://-dən sonra boşluğu silin, mətni keçidsiz necə göstərəcəyimi bilmirəm):

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

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

3. Mərkəz üzrə axtarış
Linkdəki şərhdə müsbət və mənfi cəhətlər. Şəxsən mən hesab edirəm ki, bu həll yalnız kodlaşdırma aşkarlanması üçün lazımsızdır - çox güclü olduğu ortaya çıxır. İçindəki kodlaşdırmanın müəyyən edilməsi yan təsirdir).

4. Əslində, mənim qərarım

İdeya əvvəlki bölmədən ikinci keçidə baxarkən yarandı. İdeya belədir: biz böyük bir rus mətni götürürük, müxtəlif hərflərin tezliklərini ölçürük və kodlaşdırmanı aşkar etmək üçün bu tezliklərdən istifadə edirik. İrəliyə baxaraq dərhal deyəcəyəm ki, böyük və kiçik hərflərlə bağlı problemlər olacaq. Buna görə də, həm hərflərə həssas, həm də böyük hərflərə həssas olmayan hərf tezliklərinin (gəlin bunu “spektr” adlandıraq) nümunələrini yerləşdirirəm (ikinci halda, eyni tezlikli kiçik hərfə daha böyük bir hərf əlavə etdim və hamısını sildim. daha böyükləri). Bu "spektrlərdə" tezlikləri 0,001-dən az olan bütün hərflər və boşluq kəsilir. “Müharibə və Sülh” əsərini işlədikdən sonra əldə etdiyim budur:

Hərfi-həssas "spektr":
massiv ("o" => 0,095249209893009, "e" => 0,06836817536026, "a" => 0,067481298384992, "i" => 0,0559950274004, 0,0559950274004 => 0,0274004 .... "e" => 0,002252892226507, "N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "B" => 0,001404332975790, 0,0014043329757030, 0,0018574762967903, "A" => 0,0012623590130186, "K" => 0,0011804488387602, "M" => 0,001061932790165,)

Hərflərə həssas deyil:
massiv ("O" => 0,095249209893009, "o" => 0,095249209893009, "E" => 0,06836817536026, "e" => 0,0683681753602, 0,0683681753602, 6,28,28 a" => 0,067481298384992, "VƏ" => 0,055995027400041 , "i" => 0,055995027400041, .... "C" => 0,0029893589260344, "c" => 0,0029893589260344, "sch" => 0,00246491690605, 1406, "E" => 0,002252892226507, "e " => 0,002252892226507, "F" => 0,0015961610948418, "f" => 0,0015961610948418,)

Müxtəlif kodlaşdırmalarda spektrlər (massiv açarları müvafiq kodlaşdırmada müvafiq simvolların kodlarıdır):

Sonrakı. Naməlum kodlaşdırmanın mətnini alırıq, yoxlanılan hər bir kodlaşdırma üçün cari simvolun tezliyini tapırıq və onu bu kodlaşdırmanın "reytinqinə" əlavə edirik. Ən yüksək reytinqə malik kodlaşdırma, çox güman ki, mətn kodlaşdırmasıdır.

$encodings = array("cp1251" => "specter_cp1251.php" tələb edir, "koi8r" => "specter_koi8r.php", "iso88595" => "specter_iso88595.php" tələb edir); $enc_rates = massiv(); üçün ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)];
Bu kodu özünüz işlətməyə belə cəhd etməyin - bu işləməyəcək. Bu psevdokodu nəzərdən keçirə bilərsiniz - məqaləni qarışdırmamaq üçün təfərrüatları buraxdım. $char_specter tam olaraq pastebin-də istinad edilən massivlərdir.

Nəticələr
Cədvəl sətirləri mətn kodlaşdırması, sütunlar isə $enc_rates massivinin məzmunudur.

1) $str = "Rus mətni";
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

Hər şey yaxşıdır. Həqiqi kodlaşdırma artıq digərlərindən 4 dəfə yüksək reytinqə malikdir - bu belə qısa mətn üçündür. Daha uzun mətnlər üçün nisbət təxminən eyni olacaq.


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

Vay! Tam bir qarışıqlıq. Bunun səbəbi CP1251-dəki böyük hərflərin adətən KOI8-R-dəki kiçik hərflərə uyğun olmasıdır. Kiçik hərflər, öz növbəsində, böyük olanlardan daha çox istifadə olunur. Beləliklə, biz CP1251-də başlıq sətirini KOI8-R kimi təyin edirik.
Gəlin bunu hərflərə həssaslıqla etməyə çalışaq ("spektra" hərfi həssas deyil)

1) $str = "Rus mətni";
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 METN";
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

Gördüyünüz kimi, düzgün kodlaşdırma ardıcıl olaraq həm böyük hərflərə həssas olan "spektrlər"lə (əgər sətirdə az sayda böyük hərf varsa), həm də böyük hərflərə həssas olmayanlara səbəb olur. İkinci halda, hərflərə həssas olmayanlarla, aparıcı, əlbəttə ki, o qədər də inamlı deyil, hətta kiçik xətlərdə də kifayət qədər sabitdir. Siz həmçinin hərflərin çəkiləri ilə oynaya bilərsiniz - məsələn, onları tezliyə görə qeyri-xətti edin.

5. Nəticə

Mövzu UTF-8 ilə işləməyi əhatə etmir - burada heç bir əsas fərq yoxdur, yalnız simvol kodlarını əldə etmək və sətri simvollara bölmək bir qədər uzun/daha mürəkkəb olacaq.
Bu ideyaları təkcə kiril kodlaşdırmalarına aid etmək olmaz, əlbəttə ki, sual yalnız müvafiq dillərin/kodlaşdırmaların “spektrlərində”dir.

P.S. Əgər bu, həqiqətən zəruridirsə/maraqlıdırsa, o zaman tam işləyən kitabxananın ikinci hissəsini GitHub-da yerləşdirəcəyəm. Yazıdakı məlumatların öz ehtiyaclarınız üçün belə bir kitabxananı tez bir zamanda yazmaq üçün kifayət qədər olduğuna inanıram - rus dili üçün "spektr" tərtib edilmişdir, onu asanlıqla bütün lazımi kodlaşdırmalara köçürmək olar.

Bir problemlə qarşılaşdım - səhifənin/mətnin/hər hansı kodlaşdırmanın avtomatik aşkarlanması. Tapşırıq yeni deyil və bir çox velosipedlər artıq icad edilmişdir. Məqalədə İnternetdə tapılanların qısa icmalı var - üstəlik, layiqli bir həll olduğunu düşündüyüm bir təklif.

1. Niyə mb_detect_encoding() deyil?

Bir sözlə, işləmir.

Baxaq:
// Girişdə - CP1251 kodlu rusca mətn $string = iconv("UTF-8", "Windows-1251", "O, Anna Pavlovnaya yaxınlaşdı, onun əlini öpdü, ətirli və parıldayan keçəl başını ona göstərdi və sakitcə oturdu. divanda aşağı."); // Gəlin görək md_detect_encoding() bizə nə verir. Birinci $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 // İndi $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
Gördüyünüz kimi, çıxış tam bir qarışıqlıqdır. Bir funksiyanın niyə belə davrandığı aydın olmayanda nə edirik? Düzdü, Google-da axtaraq. Əla cavab tapdım.

Nəhayət, mb_detect_encoding() istifadəsinə dair bütün ümidləri aradan qaldırmaq üçün mbstring genişləndirilməsinin mənbə koduna baxmaq lazımdır. Beləliklə, qollarınızı yuxarı çəkin və gedək:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) ( ... // sətir 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl + klikləyin:
// 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; elflists (kodlaşdırma; elflists, encoding = , sərt);
Ctrl + klikləyin:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * kodlaşdırmanı müəyyənləşdirin */ const mbfl_encoding * mbfl_identify_encoding (mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
Məqaləni lazımsız mənbələrlə qarışdırmamaq üçün metodun tam mətnini yerləşdirməyəcəyəm. Maraqlananlar özlərinə baxacaqlar. Bizi 593 nömrəli sətir maraqlandırır, burada simvolun kodlaşdırmaya uyğun olub olmadığını yoxlayırıq:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filter->filter_funksiya)(*p, filter); if (filtr->bayraq) (pis++; )
Bir baytlıq kiril üçün əsas filtrlər bunlardır:

Windows-1251 (orijinal şərhlər qorunur)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* bütün bunlar indi çox çirkindir! */ statik int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filtr) ( əgər (c >= 0x80 && c)< 0xff) filter->bayraq = 0;

başqa filtr->
KOI8-R< 0xff) filter->// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 statik int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filtr) ( əgər (c >= 0x80 && c)

bayraq = 0;
else filter->bayraq = 1; /* deyil */ qaytarmaq c; )
ISO-8859-5 (burada hər şey əyləncəlidir)

// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true (int c, mbfl_identify_filter *filtr) ( qaytarın c; )

Gördüyünüz kimi, ISO-8859-5 həmişə TRUE qaytarır (FALSE qaytarmaq üçün filter->bayraq = 1 təyin etməlisiniz).

Filtrlərə baxanda hər şey öz yerinə düşdü. CP1251-i KOI8-R-dən ayırmaq üçün heç bir yol yoxdur. Ümumiyyətlə, ISO-8859-5, əgər kodlaşdırma siyahısındadırsa, həmişə düzgün olaraq aşkar ediləcəkdir.

Ümumiyyətlə, uğursuz. Bu başa düşüləndir - ümumiyyətlə, kodlaşdırmanı yalnız simvol kodları ilə tapmaq mümkün deyil, çünki bu kodlar müxtəlif kodlaşdırmalarda kəsişir.

2. Google nələri gündəmə gətirir
Google isə hər cür alçaqlığı gündəmə gətirir. Mənbəni də bura yerləşdirməyəcəyəm, istəsəniz özünüzə baxın (http://-dən sonra boşluğu silin, mətni keçidsiz necə göstərəcəyimi bilmirəm):

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

1) yenidən simvol kodları:

2) mənim fikrimcə, çox maraqlı bir həll:
Linkdəki şərhdə müsbət və mənfi cəhətlər. Şəxsən mən hesab edirəm ki, bu həll yalnız kodlaşdırma aşkarlanması üçün lazımsızdır - çox güclü olduğu ortaya çıxır. İçindəki kodlaşdırmanın müəyyən edilməsi yan təsirdir).

4. Əslində, mənim qərarım

İdeya əvvəlki bölmədən ikinci keçidə baxarkən yarandı. İdeya belədir: biz böyük bir rus mətni götürürük, müxtəlif hərflərin tezliklərini ölçürük və kodlaşdırmanı aşkar etmək üçün bu tezliklərdən istifadə edirik. İrəliyə baxaraq dərhal deyəcəyəm ki, böyük və kiçik hərflərlə bağlı problemlər olacaq. Buna görə də, həm hərflərə həssas, həm də böyük hərflərə həssas olmayan hərf tezliklərinin (gəlin bunu “spektr” adlandıraq) nümunələrini yerləşdirirəm (ikinci halda, eyni tezlikli kiçik hərfə daha böyük bir hərf əlavə etdim və hamısını sildim. daha böyükləri). Bu "spektrlərdə" tezlikləri 0,001-dən az olan bütün hərflər və boşluq kəsilir. “Müharibə və Sülh” əsərini işlədikdən sonra əldə etdiyim budur:

Hərfi-həssas "spektr":
massiv ("o" => 0,095249209893009, "e" => 0,06836817536026, "a" => 0,067481298384992, "i" => 0,0559950274004, 0,0559950274004 => 0,0274004 .... "e" => 0,002252892226507, "N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "B" => 0,001404332975790, 0,0014043329757030, 0,0018574762967903, "A" => 0,0012623590130186, "K" => 0,0011804488387602, "M" => 0,001061932790165,)

Hərflərə həssas deyil:
massiv ("O" => 0,095249209893009, "o" => 0,095249209893009, "E" => 0,06836817536026, "e" => 0,0683681753602, 0,0683681753602, 6,28,28 a" => 0,067481298384992, "VƏ" => 0,055995027400041 , "i" => 0,055995027400041, .... "C" => 0,0029893589260344, "c" => 0,0029893589260344, "sch" => 0,00246491690605, 1406, "E" => 0,002252892226507, "e " => 0,002252892226507, "F" => 0,0015961610948418, "f" => 0,0015961610948418,)

Müxtəlif kodlaşdırmalarda spektrlər (massiv açarları müvafiq kodlaşdırmada müvafiq simvolların kodlarıdır):

Sonrakı. Naməlum kodlaşdırmanın mətnini alırıq, yoxlanılan hər bir kodlaşdırma üçün cari simvolun tezliyini tapırıq və onu bu kodlaşdırmanın "reytinqinə" əlavə edirik. Ən yüksək reytinqə malik kodlaşdırma, çox güman ki, mətn kodlaşdırmasıdır.

$encodings = array("cp1251" => "specter_cp1251.php" tələb edir, "koi8r" => "specter_koi8r.php", "iso88595" => "specter_iso88595.php" tələb edir); $enc_rates = massiv(); üçün ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$encoding] += $char_specter)];
Bu kodu özünüz işlətməyə belə cəhd etməyin - bu işləməyəcək. Bu psevdokodu nəzərdən keçirə bilərsiniz - məqaləni qarışdırmamaq üçün təfərrüatları buraxdım. $char_specter tam olaraq pastebin-də istinad edilən massivlərdir.

Nəticələr
Cədvəl sətirləri mətn kodlaşdırması, sütunlar isə $enc_rates massivinin məzmunudur.

1) $str = "Rus mətni";
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

Hər şey yaxşıdır. Həqiqi kodlaşdırma artıq digərlərindən 4 dəfə yüksək reytinqə malikdir - bu belə qısa mətn üçündür. Daha uzun mətnlər üçün nisbət təxminən eyni olacaq.


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

Vay! Tam bir qarışıqlıq. Bunun səbəbi CP1251-dəki böyük hərflərin adətən KOI8-R-dəki kiçik hərflərə uyğun olmasıdır. Kiçik hərflər, öz növbəsində, böyük olanlardan daha çox istifadə olunur. Beləliklə, biz CP1251-də başlıq sətirini KOI8-R kimi təyin edirik.
Gəlin bunu hərflərə həssaslıqla etməyə çalışaq ("spektra" hərfi həssas deyil)

1) $str = "Rus mətni";
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 METN";
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

Gördüyünüz kimi, düzgün kodlaşdırma ardıcıl olaraq həm böyük hərflərə həssas olan "spektrlər"lə (əgər sətirdə az sayda böyük hərf varsa), həm də böyük hərflərə həssas olmayanlara səbəb olur. İkinci halda, hərflərə həssas olmayanlarla, aparıcı, əlbəttə ki, o qədər də inamlı deyil, hətta kiçik xətlərdə də kifayət qədər sabitdir. Siz həmçinin hərflərin çəkiləri ilə oynaya bilərsiniz - məsələn, onları tezliyə görə qeyri-xətti edin.

5. Nəticə

Mövzu UTF-8 ilə işləməyi əhatə etmir - burada heç bir əsas fərq yoxdur, yalnız simvol kodlarını əldə etmək və sətri simvollara bölmək bir qədər uzun/daha mürəkkəb olacaq.
Bu ideyaları təkcə kiril kodlaşdırmalarına aid etmək olmaz, əlbəttə ki, sual yalnız müvafiq dillərin/kodlaşdırmaların “spektrlərində”dir.

P.S. Əgər bu, həqiqətən zəruridirsə/maraqlıdırsa, o zaman tam işləyən kitabxananın ikinci hissəsini GitHub-da yerləşdirəcəyəm. Yazıdakı məlumatların öz ehtiyaclarınız üçün belə bir kitabxananı tez bir zamanda yazmaq üçün kifayət qədər olduğuna inanıram - rus dili üçün "spektr" tərtib edilmişdir, onu asanlıqla bütün lazımi kodlaşdırmalara köçürmək olar.

İdeya - Lotereya

Kodlaşdırmanı əldə etmək fikri mənim ağlıma gəlmədi, amma təəssüf ki, indi müəllifə deyə bilmərəm, çünki təxminən 4 il əvvəl idi və bu məlumatı haradan aldığım çoxdan unudulub. Müəllif tərif təklif etdi və Python-da 1-2 kodlaşdırma üçün bir nümunə göstərdi. Onun həllinin sadəliyi məni bir kənara qoymadı və onu istədiyim nəticəyə qədər inkişaf etdirdim.
İdeyanın mahiyyəti kodlaşdırma kod cədvəllərinin özündədir. Bildiyiniz kimi, hər hansı bir kodlaşdırma öz kod cədvəlini ehtiva edir və hər bir kodlaşdırma simvoluna xüsusi bir dəyər verilir. Mən burada kodlaşdırma cədvəllərini göstərməyəcəyəm; indi onları İnternetdə tapmaq olduqca asandır.
İcra prinsipi aşağıdakı kimidir:
  1. Yoxlanan mətnin “təhlil” nəticəsini saxlamaq üçün massiv dəyişəni yaradılır. Massivin hər bir elementi müəyyən kodlaşdırma üçün nəticəni ehtiva edəcəkdir.
  2. Funksiyaya giriş kimi qəbul edilən mətn simvolik olaraq təkrarlanır.
  3. Ordinal (həmin simvolun mənası) hər simvoldan götürülür və kodlaşdırma diapazonu ilə müqayisə edilir.
  4. Əgər dəyər böyük hərf (böyük hərf) simvoluna düşürsə, bu kodlaşdırmanın nəticəsini saxlayan massiv elementinə 1 dəyəri əlavə edilir.
  5. Əgər dəyər kiçik (kiçik) simvola düşürsə, bu kodlaşdırmanın nəticəsini saxlayan massiv elementinə 3 dəyəri əlavə olunur.
  6. Həmin kodlaşdırma, daha dəqiq desək, ən çox xal toplayan onun kodlaşdırmasının nəticəsini saxlayan massivin elementi çox güman ki, orijinal kodlaşdırmadır.
Bu alqoritm KOI-8, CP1251 (windows-1251) və başqaları kimi tək baytlıq kodlaşdırmalar üçün etibarlıdır. Bununla belə, iki baytlıq kodlaşdırmalar üçün (mənim vəziyyətimdə UTF-8) bu yanaşma səhv nəticə verəcəkdir. Başlamaq üçün, böyük hərflər üçün 5 və kiçik hərflər üçün 7 əlavə edərək bu problemi həll etməyə çalışdım, amma tanınma səhvləri hələ də var idi. Bəzi təcrübələrdən sonra belə qənaətə gəldim ki, UTF-ni düzgün müəyyən etmək üçün böyük hərflər üçün nəticəyə 10, kiçik hərflər üçün 14, yəni ilkin təxminimdən 2 dəfə çox əlavə edilməlidir. Ancaq kodun daha yaxşı vizual başa düşülməsi üçün UTF simvolları üçün müvafiq olaraq 5 və 7 buraxdım və sınaq zamanı bu dəyərləri 2 artırdım və nəticəyə əlavə etdim.
Əsasən bütün alqoritm budur. Və heç bir lazımsız əngəl olmadan.
Bu funksiyanın həyata keçirilməsinə sərf etdiyim vaxtın çox hissəsi, əlbəttə ki, kod cədvəllərinin axtarışı və diapazonların düzgün təşkili idi. Bu funksiyanı ilk dəfə yazdığım zaman cari kod cədvəlini tapmaq nəinki kifayət qədər çətin idi, həm də onların içindəki simvol diapazonları təsadüfi olaraq sıçrayır. Bununla belə, mən daha sonra ən aktual (və bu günə qədər) kodlaşdırmalara qərar verdim: UTF-8, CP1251, KOI8-R, IBM866, ISO-8859-5 və MAC. Bu kodlaşdırmalar sizin üçün kifayət deyilsə, bu alqoritm əsasında kodu əlavə edə bilərsiniz.

Sözlərdən təcrübəyə

Əslində, Python-da bütün funksiya kodu belə görünür:

Kodlaşdırmalar = ( "UTF-8": "utf-8", "CP1251": "windows-1251", "KOI8-R": "koi8-r", "IBM866": "ibm866", "ISO-8859- 5": "iso-8859-5", "MAC": "mac", ) """ Mətn kodlaşdırmasının müəyyən edilməsi """ def get_codepage(str = Heç biri): böyük hərf = 1 kiçik = 3 utfupper = 5 utflower = 7 codepages = () encodings.keys(): codepages = 0, əgər str Yoxdursa və len(str) > 0: last_simb = 0 simb üçün str: simb_ord = ord(simb) """qeyri-rus simvolları simb_ord əgər " ""< 128 or simb_ord >256: əgər last_simb == 208 və (143) varsa """UTF-8""" davam edin< 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 = kod səhifələri idx = maddə qaytarılması idx
Funksiya çağırışı nümunəsi

Çap kodlaşdırmaları

Bəs PHP?

Python-dan PHP-ə hazır funksiyanı yenidən yazmaq çətin deyildi. Görünüşünə görə, o, Python-dakı anasından praktiki olaraq fərqlənmir:

/** * Mətn kodlamasını təyin edin * @param String $text Text * @return String Mətn kodlaşdırması */ funksiyası get_codepage($text = "") ( if (!empty($text)) ( $utflower = 7; $utfupper = 5; $böyük hərf = 1; $last_simb = 0; " => 0, "ISO-8859-5" => 0, "MAC" => 0,); ($a = 0; $a) üçün< strlen($text); $a++) { $char = ord($text[$a]); // non-russian characters if ($char<128 || $char>256) davam etdirmək;<176) || $char==129)) $charsets["UTF-8"] += ($utfupper * 2); if ((($last_simb==208) && (($char>// UTF-8 əgər (($last_simb==208) && (($char>143 && $char)<192) || $char==145)) || ($last_simb==209 && $char>175 && $xarakter<144)) $charsets["UTF-8"] += ($utflower * 2); // CP1251 if (($char>127 && $ işarəsi<256) || $char==184) $charsets["CP1251"] += $lowercase; if (($char>223 && $ işarəsi<224) || $char==168) $charsets["CP1251"] += $uppercase; // KOI8-R if (($char>223 && $ işarəsi<224) || $char==163) $charsets["KOI8-R"] += $lowercase; if (($char>191 && $ işarəsi<256) || $char==179) $charsets["KOI8-R"] += $uppercase; // IBM866 if (($char>222 && $ işarəsi<176) || ($char>127 && $ işarəsi<241)) $charsets["IBM866"] += $lowercase; if (($char>175 && $xarakter<160) || $char==241) $charsets["IBM866"] += $uppercase; // ISO-8859-5 if (($char>159 && $ işarəsi<240) || $char==161) $charsets["ISO-8859-5"] += $lowercase; if (($char>// UTF-8 əgər (($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 && $xarakter<160) $charsets["MAC"] += $uppercase; $last_simb = $char; } arsort($charsets); return key($charsets); } }
Funksiya çağırışı nümunəsi

221 && $ işarəsi

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

Bu funksiyanı sındırmağa çalışmamalısınız. Alqoritmdən aydın olur ki, o, giriş kimi nə qədər az mətn qəbul edərsə, funksiyanın kodlaşdırmanı səhv tanıması ehtimalı bir o qədər çox olar. Digər tərəfdən, Lev Tolstoyun cildlərini qidalandırmağın da mənası yoxdur: bu üsul 100-200 simvoldan ibarət kiçik bir cümlənin öhdəsindən yaxşı gəlir. Girişə çağırış nümunələrində kodlaşdırması müəyyən edilməli olan mətni ehtiva etməli olan müəyyən bir "test.txt" faylının bütün məzmununu göndərsəm də, mətnin kiçik bir hissəsi ola bilər (və olmalıdır) funksiya girişinə keçdi.
Qarışıq böyük və kiçik hərflərlə təhrifləri bu halda ümumiyyətlə uyğun hesab etmirəm, çünki bu üsul təxminən savadlı rus dili ilə adi, tez-tez iş üçün yazılmışdır. Və belə təcrübələr ən çox mənə bir zarafat xatırladır:

Rus ağac emalı zavodu Yapon bölməsi aldı. Rus işçiləri onun ətrafına toplaşdılar və gəlin onun necə işlədiyini anlayaq. Biri lövhəni götürüb içinə yapışdırdı. Vahid:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz Uşaqlar: Vay!!! Ekrandakı vahid: yaxşı, nə düşündün? Başqa biri kəsilməmiş bir kündə götürüb bölməyə daxil etdi. Vahidi: Zzzzzzzzzzzz Ezzozzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. Uşaqlar: Vay!!! Ekrandakı vahid: yaxşı, nə düşündün? Üçüncü adam buna dözə bilməyib, hardansa rels götürüb bölməyə yapışdırıb. Vahid: drrrrrr-tyh-tyh-tyh... Siqaret çəkməyə başladı və ekranda belə yazılmışdı: Vay!!! Uşaqlar: yaxşı, nə fikirləşdiniz!!!
Beləliklə, bu cür bükülmüş testlər üçün çox güman ki, bu funksiya olmayan bir bükülmüş alqoritmə ehtiyacınız olacaq. Təcrübədən deyim ki, 4 il istifadə etdiyim müddətdə bu üsul məni heç vaxt ruhdan salmayıb və həmişə düzgün nəticə verib.
Ümid edirəm məqaləm kiməsə faydalı olacaq.
Diqqətiniz üçün təşəkkür edirik.

Məzmunun hamısından və ya bir hissəsindən istifadə edərkən mənbəyə, yəni bloquma keçid verməyi unutmayın.

Problem yarandı: UTF-8-ə nisbətən mətn sətirinin kodlaşdırılmasını necə tez müəyyənləşdirmək olar? Biz getdikcə daha çox UNICODE kodlaşdırmasında sətirlərlə işləməliyik.

Aşağıda UNICODE (UTF-8) kodlaşdırmasının WINDOWS (win-1251) kodlamasına çevrilməsinin lazım olub-olmadığını yoxlamaq funksiyası var.

Funksiya simvol-kod çevrilməsinə əsaslanmasa da, kifayət qədər dəqiq cavab verir.

funksiyası detect_my_utf($s)( $s=urlencode($s); // bəzi hallarda - lazımsız əməliyyat (şərh bildirin) $res="0"; $j=strlen($s); $s2=strtoupper($ s) ; $s2=str_replace("%D0","",$s2=str_replace("%D1","",$s2($m=$j/); $k; əgər (($m>1.2)&&($m

Funksiyanın qısa təsviri aşkar_mənim_utf():

  • çevirmək (sətir xüsusi formata)
  • daxil olan sətirin uzunluğunu hesablayın
  • sətrin bütün hərflərini böyük hərflə yazın
  • %D0 və %D1 xüsusi kodları silin
  • yeni xəttin uzunluğunu hesablayın
  • köhnə xəttin yenisinə nisbətini alırıq

Əgər bu nisbət 1-dirsə və ya ona yaxındırsa, o zaman daxil olan sətirin UNICODE-da kodlaşdırılmadığından şübhələnir. Bu nisbət 1.2 ilə 2.2 aralığındadırsa, sətri WINDOWS win-1251 kodlaşdırmasına təhlükəsiz şəkildə yenidən kodlaya bilərsiniz.

Funksiyanın çıxışı UNICODE və ya UNICODE deyil, müvafiq olaraq 0 və ya 1-dir.

Funksiyaların icrasına dair nümunələr:

Daxil olan sətir: РїР?С?С?Р?Р?Рє С?Р?Р·Р?Р°Р?РёС? Р°Р?РёР?Р°С+РёРё Р? imageready Çevirilmiş sətir: %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 Funksiya nəticəsi: 1 Kodlanmış ifadə: imageready-də animasiya yaratma qaydası

Gələn sətir: R?S?R?R?R?S

Daxil olan sətir: РїС?Р?Р?С?Р°Р?Р?Р° С+С"РчР?РёС? РїР?С+Р°С?апаР?Р?С

Daxiletmə sətri: çertyoj bələdçisi Çevirilmiş sətir: %EF%EE%F1%EE%E1%E8%E5 %EF%EE %F0%E8%F1%EE%E2%E0%ED%E8%FE Funksiya nəticəsi: 0 Kodlanmış ifadə : rəsm bələdçisi Bu alqoritm axtarış motorunun çevrilmə statistikası xidmətinin bir hissəsi kimi müxtəlif daxil olan sətirlərin öhdəsindən yaxşı gəlir.

Saytda maraqlı materiallar:

  • Saytın axtarış sistemi marağı haqqında məqalə. Bəlkə də bəzi materiallar 10 ildən sonra köhnəlmişdir, lakin bəzi məqamlara diqqət yetirməyə dəyər.

  • Donor saytı və alıcı saytları arasında hiperlinklərin mübadiləsi probleminə baxışınız.

  • Başqa bir həyat hiyləsi. “Balda” oyununda namussuz oyunçuları məğlub etdik. Asanlıqla genişləndirilə bilən böyük sözlər bazası.

Mən müxtəlif RSS lentlərindən çoxlu mətnləri oxuyuram və onları verilənlər bazama daxil edirəm.

Əlbəttə ki, borularda istifadə olunan bir neçə fərqli simvol kodlaşdırması var, məsələn. UTF-8 və ISO-8859-1.

Təəssüf ki, bəzən mətn kodlaşdırması ilə bağlı problemlər yaranır. Misal:

1) "Fußball"dakı "ß" mənim verilənlər bazamda belə görünməlidir: "Ÿ". Əgər "Ÿ" olarsa, düzgün göstərilir.

2) Bəzən "Fußball"dakı "ß" mənim verilənlər bazamda belə görünür: "ß". Sonra, əlbəttə ki, səhv göstərilir.

3) Digər hallarda "ß" "ß" kimi saxlanılır - buna görə də heç bir dəyişiklik olmadan. Sonra da səhv göstərilir.

2 və 3-cü halların qarşısını almaq üçün nə edə bilərəm?

Necə hər şeyi eyni kodlaşdırma edə bilərəm, tercihen UTF-8? Mən utf8_encode() funksiyasını nə vaxt istifadə etməliyəm, utf8_decode() funksiyasını nə vaxt istifadə etməliyəm (təsirinin nə olduğu aydındır, amma funksiyalardan nə vaxt istifadə etməliyəm?) və girişlə nə zaman nə etməliyəm?

Mənə kömək edə və eyni kodlaşdırmanı necə edəcəyimi deyə bilərsinizmi? Bəlkə mb-detect-encoding() funksiyası ilə? Bunun üçün funksiya yaza bilərəmmi? Beləliklə, mənim problemlərim bunlardır: 1) Mətndə hansı kodlaşdırmadan istifadə edildiyini necə tapmaq olar 2) Onu UTF-8-ə necə çevirmək olar - köhnə kodlaşdırmadan asılı olmayaraq

DÜZENLE: Bu funksiya işləyəcəkmi?

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

Sınadım amma işləmir. Onun nə günahı var?

24 cavab

Əgər siz artıq mövcud UTF8 sətrinə utf8_encode() tətbiq etsəniz, o, pozulmuş UTF8 çıxışını qaytaracaq.

Bütün bu problemləri həll edən bir funksiya yaratdım. Buna Encoding::toUTF8() deyilir.

Sətirlərinizin kodlaşdırılmasının nə olduğunu bilməyə ehtiyac yoxdur. Bu, Latın1 (iso 8859-1), Windows-1252 və ya UTF8 ola bilər və ya sətir onları ehtiva edə bilər. Encoding::toUTF8() hər şeyi UTF8-ə çevirir.

Bunu ona görə etdim ki, xidmət mənə məlumat axını verirdi, hamısı qarışıqdır, UTF8 və Latın1-i bir sətirdə qarışdırırdı.

İstifadəsi:

Require_once("Encoding.php"); \ForceUTF8\Encoding istifadə edin; // İndi ad boşluğundadır. $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

Mən başqa bir funksiyanı, Encoding::fixUFT8() daxil etmişəm, hansı ki, pozulmuş görünən hər bir UTF8 sətirini düzəldəcək.

İstifadəsi:

Require_once("Encoding.php"); \ForceUTF8\Encoding istifadə edin; // İndi ad boşluğundadır. $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");

Futbol Federasiyası Kamerunası Futbol Federasiyası Futbol Federasiyası Futbol Kamerunası Futbol Federasiyası

Yeniləmə: Funksiyanı (forceUTF8) Kodlaşdırma sinfində statik funksiyalar ailəsinə çevirdim. Yeni funksiya - Encoding::toUTF8().

Əvvəlcə hansı kodlaşdırmanın istifadə olunduğunu müəyyənləşdirməlisiniz. RSS lentlərini təhlil etdiyiniz üçün (bəlkə HTTP üzərindən) kodlaşdırmanı HTTP başlığının Məzmun Tipi sahəsinin simvol dəsti parametrindən oxumalısınız. Əgər o yoxdursa, emal təlimatının kodlaşdırma atributundan kodlaşdırmanı oxuyun. Bu da yoxdursa, spesifikasiyada göstərildiyi kimi UTF-8-dən istifadə edin.

Dəyişmək Budur, yəqin ki, edəcəm:

Kodlaşdırmanı aşkar etmək çətindir.

mb_detect_encoding daxil olduğunuz bir çox namizədə əsaslanaraq təxmin etməklə işləyir. Bəzi kodlaşdırmalarda müəyyən bayt ardıcıllığı etibarsızdır, ona görə də müxtəlif namizədləri ayırd edə bilir. Təəssüf ki, eyni baytların etibarlı olduğu bir çox kodlaşdırma var (lakin fərqlidir). Bu hallarda kodlaşdırmanı müəyyən etmək mümkün deyil; Bu hallarda təxmin etmək üçün öz məntiqinizi həyata keçirə bilərsiniz. Məsələn, Yapon saytından gələn məlumatlar çox güman ki, Yapon kodlaşdırmasında olacaq.

Yalnız Qərbi Avropa dilləri ilə məşğul olduğunuz halda, gəlin üç əsas kodlaşdırmaya baxaq: utf-8, iso-8859-1 və cp-1252. Bunlar bir çox platformalar üçün standart dəyərlər olduğundan, onların da səhv bildirilməsi ehtimalı var. Məsələn. insanlar müxtəlif kodlaşdırmalardan istifadə edərlərsə, yəqin ki, bu barədə açıq olacaqlar, çünki əks halda onların proqram təminatı çox tez-tez pozulacaq. Beləliklə, kodlaşdırma bu üçündən biri kimi elan edilmədikdə, provayderə etibar etmək yaxşı bir strategiyadır. Siz hələ də mb_check_encoding istifadə edərək onun həqiqətən etibarlı olduğunu ikiqat artırmalısınız (qeyd edək ki, etibarlı olan eyni deyil - eyni giriş bir çox kodlaşdırma üçün etibarlı ola bilər). Əgər bunlardan biridirsə, onları fərqləndirmək üçün mb_detect_encoding istifadə edə bilərsiniz. Xoşbəxtlikdən, bu kifayət qədər deterministikdir; Siz sadəcə UTF-8, ISO-8859-1, WINDOWS-1252 olan düzgün aşkarlama ardıcıllığından istifadə etməlisiniz.

Kodlaşdırmanı kəşf etdikdən sonra onu daxili təmsilə çevirməlisiniz (utf-8 yeganə ağlabatan seçimdir). Utf8_encode funksiyası iso-8859-1-i utf-8-ə çevirir ki, o, yalnız həmin xüsusi giriş növü üçün istifadə olunsun. Digər kodlaşdırmalar üçün mb_convert_encoding istifadə edin.

Bu fırıldaqçı vərəqdə PHP-də UTF-8-in idarə edilməsi ilə bağlı bəzi ümumi xəbərdarlıqlar verilmişdir: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Sətirdə çoxbayt simvolları aşkar edən bu funksiya da faydalı ola bilər ():

Function detectUTF8($string) ( return preg_match("%(?: [\xC2-\xDF][\x80-\xBF] # çox uzun olmayan 2 bayt |\xE0[\xA0-\xBF][\x80- \xBF] # həddən artıq uzunluqlar istisna olmaqla |[\xE1-\xEC\xEE\xEF][\x80-\xBF](2) # düz 3 bayt |\xED[\x80-\x9F][\x80-\xBF] # surroqatlar istisna olmaqla |\xF0[\x90-\xBF][\x80-\xBF](2) # təyyarə 1-3 |[\xF1-\xF3][\x80-\xBF](3) # təyyarə 4- 15 |\xF4[\x80-\x8F][\x80-\xBF](2) # təyyarə 16)+%xs", $string); )

Bir az diqqətli olsanız, məlumat bazanızda "ß" hərfinin "Ÿ" kimi görünməli olduğunu söylədiniz.

Bu, çox güman ki, latin1 simvol kodlaması olan verilənlər bazasından istifadə etdiyiniz və ya php-mysql bağlantısının düzgün konfiqurasiya edilməməsi ilə bağlıdır, php, mysql-nin utf-8-dən istifadə etmək üçün konfiqurasiya edildiyini güman edir ki, o, məlumatları utf8 kimi göndərir, lakin sizin mysql, php-nin iso-8859-1 kimi kodlanmış məlumatları göndərdiyinə inanır, ona görə də göndərilən məlumatlarınızı yenidən utf-8 olaraq kodlaşdırmağa cəhd edə bilər və bu kimi problemlərə səbəb ola bilər.

Buna nəzər salın, bu sizə kömək edə bilər: http://php.net/manual/en/function.mysql-set-charset.php

Cavablar müxtəlif kodlaşdırmalarla kodlaşdırıla biləcəyi üçün girişdəki kodlaşdırmanı yoxlamaq lazımdır.
Aşağıdakı funksiyadan istifadə edərək aşkarlama və tərcümə etməklə bütün məzmunu UTF-8-də göndərməyə məcbur edirəm:

Funksiya fixRequestCharset() ( $ref = massiv(&$_GET, &$_POST, &$_REQUEST); foreach ($ref &$var kimi) ( foreach ($var kimi $açar => $val) ( $encoding = mb_detect_encoding ($var[ $key ], mb_detect_order(), true if (!$encoding) davam edərsə (strcasecmp($encoding, "UTF-8") != 0) ( $encoding = iconv($encoding, "); UTF-8", $var[ $key ]); əgər ($encoding === false) davam edərsə; $var[ $key ] = $encoding; ) ) ) )

Bu prosedur uzaq hostdan gələn bütün PHP dəyişənlərini UTF-8-ə çevirəcək.
Və ya kodlaşdırma aşkarlana bilmirsə və ya çevrilə bilmirsə, dəyəri nəzərə almayın.
Siz ehtiyaclarınıza uyğun olaraq fərdiləşdirə bilərsiniz.
Sadəcə dəyişənlərdən istifadə etməzdən əvvəl onu çağırın.

Kodlaşdırmanız UTF-8-də kodlaşdırıldığınız kimi görünür iki dəfə; yəni bəzi digər kodlaşdırmadan UTF-8-ə və yenidən UTF-8-ə. Sanki iso-8859-1-i iso-8859-1-dən utf-8-ə çevirmisiniz və UTF-8-ə başqa bir çevrilmə üçün iso-8859-1 kimi yeni sətirlə işlədiniz.

Etdiyiniz işin bəzi psevdokodu budur:

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

Siz cəhd etməlisiniz:

  • mb_detect_encoding() və ya istifadə etmək istədiyiniz hər şeyi istifadə edərək kodlaşdırmanı aşkar edin
  • UTF-8 varsa, iso-8859-1-ə çevirin və 1-ci addımı təkrarlayın
  • nəhayət yenidən UTF-8-ə çevirin

Güman edilir ki, "orta" dönüşümdə iso-8859-1-dən istifadə etmisiniz. Əgər Windows-1252-dən istifadə etmisinizsə, onda Windows-1252-yə (latın1) çevirin. Orijinal mənbənin kodlaşdırılması vacib deyil; Səhv, ikinci çevrilmədə istifadə etdiyiniz.

Nə baş verdiyini təxmin edirəm; bir genişləndirilmiş ASCII bayt əvəzinə dörd bayt əldə etmək üçün bir az daha çox şey edə bilərsiniz.

Alman dili də iso-8859-2 və windows-1250 (latın2) istifadə edir.

RSS lentləri üçün simvol kodlaşdırmasının dizaynı mürəkkəb görünür. Hətta adi veb səhifələr də kodlaşdırmanı çox vaxt buraxır və ya yalan danışır.

Beləliklə, kodlaşdırmanı aşkar etmək üçün düzgün üsuldan istifadə etməyə cəhd edə bilərsiniz və sonra avtomatik aşkarlamanın bir formasına (təxmin etməyə) qayıda bilərsiniz.

Bilirəm ki, bu köhnə sualdır, amma faydalı cavabın heç vaxt zərər vermədiyinə inanıram. Masaüstü proqramlar, SQLite və GET/POST dəyişənləri arasında kodlaşdırma ilə bağlı problemlər yaşayıram. Onlardan bəziləri UTF-8-də, bəziləri ASCII-də olacaq və əsasən xarici simvollar cəlb edildikdə işlər çaşqınlaşacaq.

Budur mənim həllim. O, emal etməzdən əvvəl hər səhifə yüklənməsində GET/POST/REQUEST (kukiləri buraxdım, lakin siz onları əlavə edə bilərsiniz) düzəldir. Başlıqda yaxşı işləyir. PHP mənbə kodlamasını avtomatik müəyyən edə bilmədikdə xəbərdarlıqlar verəcək, buna görə də @ istifadə edərək bu xəbərdarlıqlar dayandırılır.

//Varslarımızdakı hər şeyi verilənlər bazası ilə yaxşı oynamaq üçün UTF-8-ə çevirin... //Bizə ikiqat kodlaşdırmamağa kömək etmək üçün burada bir neçə avtomatik aşkarlamadan istifadə edin... //Kodlaşdırma aşkarlanmadıqda @ ilə mümkün xəbərdarlıqları söndürün. cəhd edin ( $proses = massiv(&$_GET, &$_POST, &$_REQUEST); while (siyahı($açar, $val) = hər ($proses)) ( foreach ($k olaraq $val => $v) ( unset($process[$key][$k]); if (is_array($v)) ( $process[$key][@mb_convert_encoding($k,"UTF-8","avtomatik")] = $ 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"); ) ) ) unset($process); ) catch(Exception $ex)()

Mən AGES ilə kodlaşdırma həllərini yoxlayıram və bu səhifə yəqin ki, illərin axtarışlarının sonudur! Qeyd etdiyiniz bəzi təklifləri yoxladım və qeydlərim bunlardır:

Bu mənim test xəttimdir:

bu, fùnctìon tərəfindən çevrilmiş onları görmək üçün xarları xüsusi konfiqurasiya etmək üçün istifadə etmədiyim "səhv yazılmışdır" xəttidir!! və bu nədir!

Səhifəmin şrifti UTF-8-dir

Əgər bu şəkildə INSERT etsəm, mənim DB-də yəqin ki, Marsdan gələn bəzi simvollar var... ona görə də onları "hissedici" UTF-8-ə çevirməliyəm. Mən utf8_encode() funksiyasını sınadım, amma yenə də yadplanetli simvollar verilənlər bazamı zəbt edirdi...

Beləliklə, mən 8 nömrəli forceUTF8 funksiyasından istifadə etməyə çalışdım, lakin DB-də saxlanılan sətir belə görünür:

Bu, "yazılmış" sətirdir, lakin mən "sòme" yaza bilmədim, onu görmək üçün xüsusi chà rs, fùnctìon tərəfindən çevrildi! və bu nədir!

Beləliklə, bu səhifədə bir az daha çox məlumat toplamaq və digər səhifələrdəki digər məlumatlarla birləşdirərək problemi bu həll yolu ilə həll etdim:

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

İndi verilənlər bazamda düzgün kodlaşdırma ilə bir simli var.

Qeyd: mysql_client_encoding funksiyasına diqqət yetirmək üçün sadəcə bir qeyd! Siz DB-yə qoşulmalısınız, çünki bu funksiya parametr kimi resurs identifikatorunu tələb edir.

Amma yaxşı, mən sadəcə INSERT-dən əvvəl bu kodlaşdırmanı edirəm, ona görə də bu mənim üçün problem deyil.

Ümid edirəm bu, bu səhifə kimi birinin mənə kömək etməsinə kömək etdi!

Hər kəsə təşəkkürlər!

mb_detect_encoding və mb_convert_encoding ilə bağlı maraqlı cəhət ondan ibarətdir ki, təklif etdiyiniz kodlaşdırmaların sırası vacibdir:

// $input əslində UTF-8 mb_detect_encoding ($input, "UTF-8", "ISO-8859-9, UTF-8"); // ISO-8859-9 (YANLIŞ!) mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9"); // UTF-8 (OK)

Beləliklə, gözlənilən kodlaşdırmaları təyin edərkən xüsusi bir sıradan istifadə edə bilərsiniz. Ancaq unutmayın ki, bu qüsursuz deyil.

Echo mb_detect_encoding($str, "avtomatik");

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

Nəticələrin nə olduğunu bilmirəm, amma sizə təklif edirəm ki, müxtəlif kodlaşdırmalı kanallarınızdan bəzilərini götürün və mb_detect_encoding-in işləyir, ya yox.

Yeniləyin
auto "ASCII, JIS, UTF-8, EUC-JP, SJIS" üçün qısadır. sətri iconv ilə utf-8-ə çevirmək üçün istifadə edə biləcəyiniz aşkar edilmiş kodlaşdırmanı qaytarır.

Mən onu sınaqdan keçirməmişəm, ona görə də heç bir zəmanət yoxdur. və bəlkə daha asan bir yol var.

Bu versiya alman dili üçündür, lakin siz $CHARSETS və $TESTCHARS-ı dəyişə bilərsiniz

Sinif CharsetDetector ( şəxsi statik $CHARSETS = massiv("ISO_8859-1", "ISO_8859-15", "CP850"); özəl statik $TESTCHARS = massiv("€", "ä", "Ä", "ö", "Ö", "ü", "Ü", "ß"); ictimai statik funksiya çevirir($string) ( qaytar self::__iconv($string, self::getCharset($string)); ) ictimai statik funksiya getCharset ($string) ( $normalized = self::__normalize($string); if(!strlen($normalized))qaytar "UTF-8"; $best = "UTF-8"; $charcountbest = 0; foreach (self) ::$CHARSETS $charset kimi) ( $str = self::__iconv($normallaşdırılmış, $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 $mətn."
"; ) return $best; ) özəl statik funksiya __normalize($str) ( $len = strlen($str); $ret = ""; for($i = 0; $i)< $len; $i++){ $c = ord($str[$i]); if ($c >128) ( əgər (($c > 247)) $ret .=$str[$i]; elseif ($c > 239) $bayt = 4; elseif ($c > 223) $bayt = 3; elseif ($) c > 191) $bayt = 2; else $ret .=$str[$i] əgər (($i + $bayt) > $len) $ret .=$str[$i]; isə ($bayt > 1) ( $i++; $b = ord($str[$i]); əgər ($b)< 128 || $b >191) ($ret .=$ret2; $ret2=""; $i+=$bayt-1;$bayt=1; fasilə;) başqa $ret2.=$str[$i];

$bayt--;

) ) ) $ret qaytarmaq; ) özəl statik funksiya __iconv($string, $charset) ( iconv qaytarın ($charset, "UTF-8" , $string); ) )

Latin1 I/O sessiyasında utf8 məlumatlarını latin1 cədvəlinə ötürmək bu iyrənc quş quşlarını verir. Bunu hər gün pərakəndə mağazalarda görürəm. Geri və irəli doğru görünə bilər. Ancaq phpmyadmin həqiqəti göstərəcək. MySQL-ə hansı kodlaşdırmadan keçdiyinizi söyləsəniz, sizin üçün mysql məlumatlarını emal edəcəksiniz.

Mövcud mysql şifrəli məlumatların necə bərpası müzakirə üçün başqa bir sualdır :)