Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Kodowanie znaków, chyba nietrywialne, jak rozpoznać kodowanie znakó w pliku CSV
skleps
post
Post #1





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


Muszę pobrać dane z zewnętrznego pliku CSV.
Wszystko cacy, ale całość rozbija się o kodowanie znaków. Ten kto stworzył tego CSV zakodował tak znaki, że nie mogę dojść do ładu i składu, więc może ktoś z forum ma większe doświadczenie w tym hardkorze.
W sumie muszę zawartość zakodować do iso-8859-2 i nakarmić tym bazę MySQL. Sądząc po długości stringa, kodowanie jest dwubajtowe na znak, czyli np. "tekst" wg strlen zajmuje 11.
Więc po kolei:

1. Gdy CSV testowo importuję do Openoffice Calc, to prawidłowe polskie znaki są, gdy wybiorę "Unicode", gdy wybiorę "Unicode (UTF-7)" lub "Unicode (UTF-8)" to mam krzaki.

2. Grzegżółka twierdzi że kodowanie to "Kodowanie: Unicode UCS2 LE (Intel)", ale mb_convert_encoding($tekst,"ISO-8859-2","ucs-2le") daje w wyniku krzaczki (inne wariancje ucs też)

3. Z poziomu php funkcja mb_detect_encoding twierdzi że kodowanie to UTF-8 (lub ASCII gdy nie ma w polu polskich znaczków), ale mb_convert_encoding($tekst,"ISO-8859-2","UTF-8") daje w wyniku krzaczki (przeglądarka jest ustawiona na iso-8859-2).

4. rozzłoszczony zużytym na poszukiwania czasem zrobiłem pętęlkę:
  1. foreach (mb_list_encodings() as $value) {
  2. echo '<br>'. mb_convert_encoding($tekst,"ISO-8859-2",$value);
  3. }

i żaden wynik w przeglądarce nie wygląda prawidłowo.

Tak więc chwilowo nie mam pomysłu i jestem otwarty na propozycje jak mogę jeszcze ten temat ugryźć....





Go to the top of the page
+Quote Post
Crozin
post
Post #2





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Weź sobie całe źródło zrzuć do heksadecymalnej formy zapisu bajtów, a następnie w jakimś edytorze HEX (Notepad++ ma plugin, PSPad ma wbudowany) zobacz jakie bajty odpowiadają charakterystycznym znaczkom (np. "a", "ś", "<"). Wiedząc już jakie bajty reprezentują dany znak łatwo będzie znaleźć jakie jest to kodowanie.
Go to the top of the page
+Quote Post
skleps
post
Post #3





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


Cytat(Crozin @ 12.12.2011, 23:45:03 ) *
Weź sobie całe źródło zrzuć do heksadecymalnej formy zapisu bajtów, a następnie w jakimś edytorze HEX (Notepad++ ma plugin, PSPad ma wbudowany) zobacz jakie bajty odpowiadają charakterystycznym znaczkom (np. "a", "ś", "<"). Wiedząc już jakie bajty reprezentują dany znak łatwo będzie znaleźć jakie jest to kodowanie.


Zdanie: Poznań

W hexie jest: 5000 6F00 7A00 6E00 6100 4401

Łódź = 4101 F300 6400 7A01

ę = 1901

ł = 4201

czyli na pierwszy rzut oka jest to jakiś unicode

Ten post edytował skleps 13.12.2011, 10:16:27
Go to the top of the page
+Quote Post
Crozin
post
Post #4





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Wygląda to na UTF-16LE.
Go to the top of the page
+Quote Post
skleps
post
Post #5





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


Myślałem podobnie, ale

  1. $tekst2 = mb_convert_encoding($tekst,"iso-8859-2","UTF-16LE");
  2. echo tekst2 ;


w przeglądarce ustawionej na iso-8859-2 wyświetla się: questionmark.gifquestionmark.gifquestionmark.gifquestionmark.gifquestionmark.gif?

Kawałek pliku CSv wrzuciłem pod adresem:
http://chomikuj.pl/iksow/Dokumenty/plikcsv,1241323892.csv
Go to the top of the page
+Quote Post
Crozin
post
Post #6





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


W pliku mamy BOM (0xFF 0xFE), nazwy miast oddzielone średnikiem oraz znak nowej linii (CRLF) - wszystko wskazuje na to, że jest to UTF-16LE.
Sprawdź czy mb_convert_encoding / iconv poprawnie konwertuje tekst na ISO-8859-2 - ta sama metoda, podejrzyj wygenerowane bajty.
Go to the top of the page
+Quote Post
skleps
post
Post #7





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


Na razie dostałem odpowiedź "na około" że jest to zapisany wynik zapytania z bazy.


  1. $tekst2 = mb_convert_encoding($tekst,"iso-8859-2","UTF-16LE");
  2. $fp = fopen('plikwynikowy', 'w');
  3. fwrite($fp, $tekst2);
  4. fclose($fp);


W pliku wynikowym dostaję 3F3F3F3F3F3F3F3F

Jeśli zas zrobię mb_convert_encoding($tekst,"iso-8859-2","UCS-2");

to w pliku Łódź = 41 3F 64 7A


Powoll zaczynam dojrzewać do myśli, że napiszę własną funkcję konwertującą, na chama wypisze sobie wszystkie literki i interesujące mnie znaczki...

Ten post edytował skleps 13.12.2011, 11:40:30
Go to the top of the page
+Quote Post
Crozin
post
Post #8





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


  1. $tekst2 = mb_convert_encoding($tekst,"iso-8859-2","UTF-16LE");
Sprawdziłem na swoim serwerze i działa to niemal bez problemów - nie radzi sobie jedynie z BOM-em, ale tego można od biedy przyciąć:
  1. $fileContents = substr($fileContents, 2);
Można też pominąć informację o kolejności bajtów (podając samo UTF-16), wtedy też odczyta to sobie na podstawie BOM-u i poprawnie go odczyta.

W takim przypadku radziłbym upewnić się czy aby na pewno problemem nie jest samo wyświetlanie tekstu w przeglądarce oraz czy aby na pewno PHP w Twoim przypadku wspiera UTF-16/UTF-16LE.

Ten post edytował Crozin 13.12.2011, 11:45:22
Go to the top of the page
+Quote Post
skleps
post
Post #9





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


Cytat(Crozin @ 13.12.2011, 11:43:09 ) *
W takim przypadku radziłbym upewnić się czy aby na pewno problemem nie jest samo wyświetlanie tekstu w przeglądarce


Odpada, wtedy w wygenerowanym pliku byłoby dobrze, ale źle się wyświetlało.

Cytat(Crozin @ 13.12.2011, 11:43:09 ) *
czy aby na pewno PHP w Twoim przypadku wspiera UTF-16/UTF-16LE.


To może być prędzej - jak to można sprawdzić?
Serwer to vps na debianie, być może faktycznie czegoś mu brakować, bo instalacja w miarę standardowa.
Go to the top of the page
+Quote Post
Crozin
post
Post #10





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


http://www.php.net/manual/en/function.mb-list-encodings.php
Go to the top of the page
+Quote Post
skleps
post
Post #11





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


Cytat(Crozin @ 13.12.2011, 11:54:30 ) *



no nie, to to od razu sprawdziałem wcześniej

  1. foreach (mb_list_encodings() as $value) {
  2. echo '<br>'. $value;
  3. }


i wynik:
  1. pass
  2. auto
  3. wchar
  4. byte2be
  5. byte2le
  6. byte4be
  7. byte4le
  8. BASE64
  9. UUENCODE
  10. HTML-ENTITIES
  11. Quoted-Printable
  12. 7bit
  13. 8bit
  14. UCS-4
  15. UCS-4BE
  16. UCS-4LE
  17. UCS-2
  18. UCS-2BE
  19. UCS-2LE
  20. UTF-32
  21. UTF-32BE
  22. UTF-32LE
  23. UTF-16
  24. UTF-16BE
  25. UTF-16LE
  26. UTF-8
  27. UTF-7
  28. UTF7-IMAP
  29. ASCII
  30. EUC-JP
  31. SJIS
  32. eucJP-win
  33. SJIS-win
  34. CP51932
  35. JIS
  36. ISO-2022-JP
  37. ISO-2022-JP-MS
  38. Windows-1252
  39. ISO-8859-1
  40. ISO-8859-2
  41. ISO-8859-3
  42. ISO-8859-4
  43. ISO-8859-5
  44. ISO-8859-6
  45. ISO-8859-7
  46. ISO-8859-8
  47. ISO-8859-9
  48. ISO-8859-10
  49. ISO-8859-13
  50. ISO-8859-14
  51. ISO-8859-15
  52. ISO-8859-16
  53. EUC-CN
  54. CP936
  55. HZ
  56. EUC-TW
  57. BIG-5
  58. EUC-KR
  59. UHC
  60. ISO-2022-KR
  61. Windows-1251
  62. CP866
  63. KOI8-R
  64. ArmSCII-8



Bardziej myślałem że to może jakiś błąd pliku, błąd generowania pliku lub błąd w obsłudze kodowania mimo tego, że na liście jest.

Ten post edytował skleps 13.12.2011, 12:03:37
Go to the top of the page
+Quote Post
szmerak
post
Post #12





Grupa: Zarejestrowani
Postów: 286
Pomógł: 12
Dołączył: 23.11.2006
Skąd: WL

Ostrzeżenie: (0%)
-----


Cytat(skleps @ 12.12.2011, 23:22:49 ) *
żaden wynik w przeglądarce nie wygląda prawidłowo.

Tak więc chwilowo nie mam pomysłu i jestem otwarty na propozycje jak mogę jeszcze ten temat ugryźć....


Zrobiłem kilka testów i równierz mam krzaczki na iso, tak więc ustawienia przeglądarki odpadają i ustawienia serwera także...
Gdy konwertowałem na utf8 to bodajże 3 były OK ale przy kodowaniu utf8..

Ten post edytował szmerak 13.12.2011, 14:30:57
Go to the top of the page
+Quote Post
skleps
post
Post #13





Grupa: Zarejestrowani
Postów: 142
Pomógł: 9
Dołączył: 3.03.2011

Ostrzeżenie: (0%)
-----


No i chyba wiem, czemu Crozin ma dobrze a ja i ew. inni źle. Natrknąłem się w sieci na informację:

"Nie da się odczytać pliku, zawierającego polskie ogonki, zakodowanego w UTF-16LE (standard Windowsa, pliki wypluwane np. przez PowerShella) przy użyciu funkcji php file(). Tzn. można ale przy konwersji iconv() dostajemy i tak chińskie krzaki. Plik trzeba odczytać przy pomocy file_get_contents() i wtedy już ładnie konwertuje. Dopiero potem można bawić się w cięcie stringa w tablicę."

Sprawdzę to i ew. zamkniemy temat...




EDIT:
Sprawdziłem, faktycznie jest jakiś bug w php i podsumowanie:

Jeśli zaczytujemy plik tekstowy / csv z pliku zakodowanego "UTF-16LE" to należy plik wczytać funkcją file_get_contents() !

Ten post edytował skleps 14.12.2011, 00:03:59
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 20.08.2025 - 07:32