![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 220 Pomógł: 0 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
Dostałem bazę danych w której dane były wpisane w różnych kodowaniach. Część w językach europejskich a cześć w azjatyckich, przy czym teksty powinny zawierać tylko znaki łacińskie. Teksty z bazy są wyświetlane przy użyciu kodowania utf8 ale na niektórych komputerach w miejscach spacji albo przecinków pojawiają się krzaki. Czyli muszę teraz przekonwertować wszystkie wpisy w bazie na utf8. Ale nie znam kodowań źródłowych, część jest w UTF8, cześć w GB2312, część w różnych wersjach ISO (np iso-8859-1).
W dodatku bazą jest SQLITE, która, ponoć domyślnie używa UTF8. Jak zamienić to kodowanie nie uszkadzając tekstów? Przejrzałem funkcje z pakietu multibyte ale nie działają w 100% dobrze. Jakieś pomysły? pozdrawiam Ten post edytował nowy_pehapowiec 18.11.2009, 13:21:53 |
|
|
![]()
Post
#2
|
|
![]() Grupa: Moderatorzy Postów: 8 989 Pomógł: 1550 Dołączył: 8.08.2008 Skąd: Słupsk/Gdańsk ![]() |
Pokaż jak używałeś funkcji z multibyte.
Co prawda jeszcze nigdy mnie nie zawiodły ale warto sprawdzić czy użyłeś ich poprawnie. -------------------- |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 220 Pomógł: 0 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
Najpierw sprawdziłem jakie jest kodowanie:
echo mb_detect_encoding( $a ) //dostałem w wyniku UTF-8 a to nie prawda. potem mimo wszystko spróbowałem konwersji: $a = mb_convert_encoding( $a ); i zapisu do pliku $p = fopen( 'p.txt', 'a+' ); fwrite( $p, $a ); i dostałem efekcie krzaki w niektórych miejscach. Czyli nic się nie zmieniło. Coś zrobiłem źle? Co takiego, czemu to nie działa? |
|
|
![]()
Post
#4
|
|
![]() Grupa: Moderatorzy Postów: 8 989 Pomógł: 1550 Dołączył: 8.08.2008 Skąd: Słupsk/Gdańsk ![]() |
Jak używasz mb_detect_encoding to używaj jej z drugim parametrem np
Po tej operacji do przekodowania ciągu możesz użyć iconv. -------------------- |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 220 Pomógł: 0 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
wookieb ale problem w tym, że ja nie wiem jakie pola w bazie mają jakie kodowanie.
Nie rozumiem jeszcze po co mam używać iconv? Czy samo zastosowanie mb_convert_encoding nie wystarczy? Proszę czy mógłbyś mi wytłumaczyć jak po kolei zrobić tą konwersje? I jeszcze jedno jak wyciąć ze $stringu znaki spoza kodowania utf-8? Czyli co zrobić, żeby w konwertowanym stringu zostawić tylko znaki które są w utf-8 i nie potrzeba instalować na kompie kodowania chińskiego? Sprawdziłem jeszcze, że funkcja echo iconv_get_encoding ( $a ) nic nie zwraca. A wywołanie $a = iconv('gb2312','UTF-8', $a); powoduje błąd Detected an illegal character in input string Co robić? Ten post edytował nowy_pehapowiec 19.11.2009, 11:29:20 |
|
|
![]()
Post
#6
|
|
![]() Grupa: Moderatorzy Postów: 8 989 Pomógł: 1550 Dołączył: 8.08.2008 Skąd: Słupsk/Gdańsk ![]() |
Trochę pomyślunku.
Przecież napisałeś, że znasz przynajmniej 3 kodowania znaków a to JUŻ DUŻO INFORMACJI. Podałem ci jak masz użyć mb_detect_encoding, której podajesz jaki drugi argument KODOWANIA JAKIE ZNASZ (przykład masz nawet w manualu). Przeleć po tych ciągach i zobacz dla których funkcja mb_detect_encoding nie jest w stanie wykryć kodowania, olejesz je i potem pokombinujesz jakie to może być kodowanie (np pozgadywać). Dla tych których wykryło odpowiednie kodowanie użyć iconv
I zapisujesz ten ciąg w bazie. Pach masz kodowanie utf-8. -------------------- |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 220 Pomógł: 0 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
mb nie wykrywa żadnego kodowania poprawnie. Kodowanie znam tylko na podstawie zgadywania ze zmian ustawień w FireFox. Jakieś sugestie? Np jak pozamieniać wybrany robaczek na znak z zestawu utf-8?
|
|
|
![]()
Post
#8
|
|
![]() Grupa: Moderatorzy Postów: 8 989 Pomógł: 1550 Dołączył: 8.08.2008 Skąd: Słupsk/Gdańsk ![]() |
Wrzuć tą tabelę do jakieś pliku i wystam. Mogę się założyć, że mb + iconv dadzą rade.
Tylko poprawnie wyeksportuje tabelę. Ten post edytował wookieb 19.11.2009, 14:05:01 -------------------- |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 220 Pomógł: 0 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
Udało mi się ustalić, że w tekście są jednocześnie znaki UTF i inne. Dlatego, nie udaje się żadnym funkcjom ustalić kodowana - bo w jednym stringu jest ich kilka.
Co robić? Bardzo proszę o pomoc - sprawa jest dla mnie niezmiernie ważna. A coś czuje, że sam jej nie rozwiąże. pozdrawiam Po godzinach spędzonych na przeszukiwaniu neta obawiam się, że nie ma gotowego rozwiązania mojego problemu. Ponieważ znaków niezgodnych z UTF8 nie jest dużo, więc będę zamieniać wartości bitów. W edytorze HEX sprawdzę, które bity odpowiadają za "złe" znaki, skopiuje ich wartości i przy pomocy zwykłego str_replace zamienię na takie wartości HEX jakie odpowiadają dobrym znakom. Czyli rzecz się sprowadza do zrobienia tabelki z odpowiednimi wartościami HEX. Jest jeden problem. Mogę coś przeoczyć. Dlatego potrzebuje listy wszystkich znaków z UTF-8 w zapisie HEX, żeby sprawdzić czy nic nie pomniałem. Czy ktoś wie gdzie znajdę taką listę? I dwa jak sprawdzić czy w stringu występują znaki inne niż w wybranej tablicy? Czyli jak sprawdzić czy string zawiera znaki z poza UTF-8, ewentualnie ASCII? Pomoże ktoś? Ten post edytował nowy_pehapowiec 20.11.2009, 12:57:04 |
|
|
![]()
Post
#10
|
|
![]() Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Istnieje możliwość takiego sprawdzenia. Sekwencje wielobajtowe w UTF-8 zostały tak dobrane, że kontrola błędu jest stosunkowo prosta bez żadnej dodatkowej tablicy znaków (btw. powodzenia z używaniem takowej - standard Unicode liczy miliony pozycji
![]() 0xxxxxxx - normalny znak ASCII z zakresu 0-127. 10xxxxxx - drugi lub każdy kolejny bajt "wyższych" znaków Unicode. Może być poprzedzony jedynie poprawną sekwencją startową UTF-8 lub innym 10xxxxxx. Jeśli jest przed nim coś innego, taki znak jest błędnie zakodowany. Sekwencje startowe UTF-8 - kodują znaki od numerów 128 w górę. 110xxxxx - sekwencja dwubajtowa. Po niej musi następować JEDEN bajt 10xxxxxx. 1110xxxx - sekwencja trzybajtowa. Po niej muszą następować DWA bajty 10xxxxxx. 11110xxx - sekwencja czterobajtowa... itd. Sprawdzanie poprawności można wykonać przy pomocy prostego automatu skończonego (de facto wyrażenie regularne by wystarczyło, ale jak masz jeszcze po drodze poprawiać źle zakodowane znaki, to musisz własny zaklepać). Potrzebna Ci jest pętla, która jedzie po ciągu od początku do końca oraz jedna zmienna w której masz zapisany aktualny stan. Na Wikipedii możesz sobie doczytać, jak taki automat działa, bo tu szkoda na to miejsca. Opiszę jedynie tabelę przejść w postaci (stan, aktualny znak) -> nowy stan (domyślny, 0xxxxxxx) -> domyślny (domyślny, 10xxxxxx) -> błąd_1 (domyślny, 110xxxxx) -> 2b_1 (domyślny, 1110xxxx) -> 3b_1 (domyślny, 11110xxx) -> 4b_1 (domyślny, 111110xx) -> 5b_1 (domyślny, 1111110x) -> 6b_1 Sprawdzanie sekwencji dwubajtowej: (2b_1, 10xxxxxx) -> domyślny (2b_1, xxxxxxxx) -> błąd_2 Sprawdzanie dla sekwencji trzybajtowej: (3b_1, 10xxxxxx) -> 3b_2 (3b_1, xxxxxxxx) -> błąd_2 (3b_2, 10xxxxxx) -> domyślny (3b_2, xxxxxxxx) -> błąd_2 Analogicznie konstruujesz stany dla sekwencji 4, 5 i 6-bajtowych. Jak dojdziesz do końca, to jest poprawne. Taki automat sprawdza jedynie poprawność, ty go rozbudujesz o dodatkowy kod: 1. Przy przejściu do stanu "domyślny" przepisujesz znak do bufora $poprawny zawierającego poprawiony ciąg. 2. Przy napotkaniu sekwencji startowej UTF-8, czyścisz bufor $znakUTF i wprowadzasz tam odczytany bajt. 3. W stanach typu 3b_2, 2b_1 itd. czyli tych, co sprawdzają kolejne bajty znaku UTF-8 dodajesz je do bufora $znakUTF. Jeśli to był ostatni bajt danej sekwencji, dodajesz $znakUTF do bufora $poprawny. 4. Przy wejściu do stanu błąd_1 masz symbol z jakiegoś kodowania jednobajtowego (np. ISO-8859-2), który konwertujesz na odpowiadającą mu kilkubajtową sekwencję UTF-8. Sekwencję tę dodajesz do bufora $poprawny i natychmiast przechodzisz do stanu domyślny tak, żeby analiza mogła od kolejnego znaku trwać dalej. 5. Przy wejściu do stanu błąd_2 masz sytuację, gdy sekwencja UTF-8 rozpoczęła się poprawnie, ale w którymś miejscu pojawił się błąd. Wtedy bierzesz każdy bajt ze $znakUTF, traktujesz go jako jakiś symbol w kodowaniu jednobajtowym, konwertujesz na odpowiadającą mu sekwencję UTF-8 i dodajesz ją do bufora $poprawny. Po zakończeniu od razu zmieniasz stan na domyślny, by od następnego znaku rozpocząć dalej normalną analizę. Oczywiście nic nie zagwarantuje Ci 100% poprawnej konwersji ciągu, w którym masz wymieszany UTF-8 i kodowania jednobajtowe. Jeśli ciąg znaków z przedziału 128-255 przypadkiem będzie tworzyć poprawną sekwencję znaku UTF-8, każdy algorytm, który nie próbuje zrozumieć czytanego tekstu nie zasygnalizuje tego jako błąd. Sytuacja taka jest mało prawdopodobna, ale możliwa. Ten post edytował Zyx 25.11.2009, 10:31:30 -------------------- Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0 |
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 220 Pomógł: 0 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
Zyx Twoje rozwiązanie jest super, ale ma dużą wadę, jego napisanie jest troszkę trudne i bardzo czasochłonne.
Mi udało się wymyślić coś innego, ale nie wiem czy będzie dobre. 1 Wklejam tablice wartości HEX dla kodowania UTF-8 (http://www.utf8-chartable.de/). Tekst jest po angielsku, więc powinno wystarczyć, ale o tym potem. 2 Wszystkie pola z tekstem sklejam w jedną zmienną. 3 Następnie funkcją str_split rozdzielam znaki w tekście. 4 Każdy znak zamieniam funkcją bin2hex na wartości HEX i zapasuje do tablicy 5 Porównuje tablice z hexami z UTF-8 i z hexami z tekstu. Te które są w tekście a których nie ma w UTF zapisuje do kolejnej tablicy. 6 Sprawdzam jaka sekwencja hex w UTF-8 jest odpowiednikiem wybranych znaków. 7 Zamieniam w każdym polu "złe"hexy na "dobre" Czy to będzie działać? Jest w tym może jakiś błąd? pozdro |
|
|
![]() ![]() |
![]() |
Aktualny czas: 20.08.2025 - 13:31 |