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: 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 (IMG:style_emoticons/default/smile.gif) ). Będę podawać tutaj wartości bajtów zapisane binarnie, gdyż tam najlepiej to widać (x - dowolna wartość, koduje numer znaku).
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 |
|
|
|
nowy_pehapowiec Problem z konwersją nieznanych kodowań na UTF8 w bazie SQLITE 18.11.2009, 13:08:12
wookieb Pokaż jak używałeś funkcji z multibyte.
Co prawda ... 18.11.2009, 13:21:21
nowy_pehapowiec Najpierw sprawdziłem jakie jest kodowanie:
echo mb... 19.11.2009, 10:33:54
wookieb Jak używasz mb_detect_encoding to używaj jej z dru... 19.11.2009, 10:51:52
nowy_pehapowiec wookieb ale problem w tym, że ja nie wiem jakie po... 19.11.2009, 11:05:55
wookieb Trochę pomyślunku.
Przecież napisałeś, że znasz pr... 19.11.2009, 12:05:37
nowy_pehapowiec mb nie wykrywa żadnego kodowania poprawnie. Kodowa... 19.11.2009, 13:22:41
wookieb Wrzuć tą tabelę do jakieś pliku i wystam. Mogę się... 19.11.2009, 13:39:17
nowy_pehapowiec Udało mi się ustalić, że w tekście są jednocześnie... 20.11.2009, 12:56:48
nowy_pehapowiec Zyx Twoje rozwiązanie jest super, ale ma dużą wadę... 25.11.2009, 14:05:49 ![]() ![]() |
|
Aktualny czas: 26.12.2025 - 16:29 |