Jak mogę przetestować kodowanie pliku tekstowego… Czy jest prawidłowy i co to jest?

46

Mam kilka .htmplików, które otwierają się w Gedit bez żadnego ostrzeżenia / błędu, ale kiedy otwieram te same pliki Jedit, ostrzega mnie przed nieprawidłowym kodowaniem UTF-8 ...

Metatag HTML stwierdza „charset = ISO-8859-1”. Jedit zezwala na listę zastępczych kodowań i listę automatycznych detektorów kodowania (obecnie „BOM XML-PI”), więc mój bezpośredni problem został rozwiązany. Ale to zmusiło mnie do zastanowienia się: co, jeśli nie ma tam metadanych?

Kiedy informacje o kodowaniu są po prostu niedostępne, czy istnieje program CLI, który może „odgadnąć”, które kodowanie może mieć zastosowanie?

I chociaż jest to nieco inna kwestia; czy istnieje program CLI, który testuje ważność znanego kodowania?

Peter.O
źródło
Podobne do „Jak automatycznie wykryć kodowanie pliku tekstowego?” superuser.com/questions/301552/…
buzz3791
Zobacz także stackoverflow.com/q/805418/821436 :-)
Przywróć Monikę - M. Schröder

Odpowiedzi:

60

fileKomenda sprawia, że „najlepiej domysły” o kodowaniu. Użyj tego -iparametru, aby wymusić filewydrukowanie informacji o kodowaniu.

Demonstracja:

$ file -i *
umlaut-iso88591.txt: text/plain; charset=iso-8859-1
umlaut-utf16.txt:    text/plain; charset=utf-16le
umlaut-utf8.txt:     text/plain; charset=utf-8

Oto jak stworzyłem pliki:

$ echo ä > umlaut-utf8.txt 

Obecnie wszystko jest utf-8. Ale przekonaj się:

$ hexdump -C umlaut-utf8.txt 
00000000  c3 a4 0a                                          |...|
00000003

Porównaj z https://en.wikipedia.org/wiki/Ę#Computer_encoding

Konwertuj na inne kodowania:

$ iconv -f utf8 -t iso88591 umlaut-utf8.txt > umlaut-iso88591.txt 
$ iconv -f utf8 -t utf16 umlaut-utf8.txt > umlaut-utf16.txt 

Sprawdź zrzut heksowy:

$ hexdump -C umlaut-iso88591.txt 
00000000  e4 0a                                             |..|
00000002
$ hexdump -C umlaut-utf16.txt 
00000000  ff fe e4 00 0a 00                                 |......|
00000006

Utwórz coś „nieważnego”, mieszając wszystkie trzy:

$ cat umlaut-iso88591.txt umlaut-utf8.txt umlaut-utf16.txt > umlaut-mixed.txt 

Co filemówi:

$ file -i *
umlaut-iso88591.txt: text/plain; charset=iso-8859-1
umlaut-mixed.txt:    application/octet-stream; charset=binary
umlaut-utf16.txt:    text/plain; charset=utf-16le
umlaut-utf8.txt:     text/plain; charset=utf-8

bez -i:

$ file *
umlaut-iso88591.txt: ISO-8859 text
umlaut-mixed.txt:    data
umlaut-utf16.txt:    Little-endian UTF-16 Unicode text, with no line terminators
umlaut-utf8.txt:     UTF-8 Unicode text

fileKomenda nie ma pojęcia „ważne” lub „nieprawidłowe”. Po prostu widzi niektóre bajty i próbuje zgadnąć, jakie może być kodowanie. Jako ludzie możemy być w stanie rozpoznać, że plik jest plikiem tekstowym z niektórymi umlautami w „złym” kodowaniu. Ale jako komputer potrzebowałby sztucznej inteligencji.

Można argumentować, że heurystyka filejest pewnego rodzaju sztuczną inteligencją. Jednak nawet jeśli jest, jest bardzo ograniczony.

Oto więcej informacji o filepoleceniu: http://www.linfo.org/file_command.html

lesmana
źródło
Dzięki, działało ... Próbowałem zgłosić , but without any option :( ... I've now also tried a mixof UTF-16 and UTF-8 and ISO-8859-1. plik file -i unknown-8bit. Tak więc wydaje się to również odpowiedzią na: „Jak wykryć nieprawidłowe / nieznane kodowanie”
Peter.O,
Dla tych, którzy się tu dostają i są na Macu, jest file -Ito wielkie „i” zamiast małych liter.
samuraiseoul
21

Nie zawsze jest możliwe ustalenie, na czym polega kodowanie pliku tekstowego. Na przykład sekwencja bajtów \303\275( c3 bdw systemie szesnastkowym) może być ýw UTF-8 lub ýw latin1, Ă˝w latin2 lub w BIG-5 i tak dalej.

Niektóre kodowania mają nieprawidłowe sekwencje bajtów, więc na pewno można je wykluczyć. Dotyczy to w szczególności UTF-8; większość tekstów w większości kodowań 8-bitowych jest niepoprawna UTF-8. Można przetestować za ważnego UTF-8 z isutf8od moreutils lub z iconv -f utf-8 -t utf-8 >/dev/null, między innymi.

Istnieją narzędzia, które próbują odgadnąć kodowanie pliku tekstowego. Mogą popełniać błędy, ale często działają w praktyce, o ile celowo nie próbujesz ich oszukać.

  • file
  • PerlEncode::Guess (część standardowej dystrybucji) próbuje kolejno kodować ciąg bajtów i zwraca pierwsze kodowanie, w którym ciąg jest poprawnym tekstem.
  • Enca jest zgadywaczem kodowania i konwerterem. Możesz nadać mu nazwę języka i tekst, który, jak przypuszczasz, jest w tym języku (obsługiwane języki to głównie języki wschodnioeuropejskie) i próbuje odgadnąć kodowanie.

Jeśli w pliku znajdują się metadane (HTML / XML charset=, TeX \inputenc, emacs -*-coding-*-,…), zaawansowane edytory, takie jak Emacs lub Vim, często potrafią parsować te metadane. Nie jest to jednak łatwe do zautomatyzowania z poziomu wiersza poleceń.

Gilles „SO- przestań być zły”
źródło
Dzięki za dobry przegląd ... Tak, „najlepsze zgadywanie” może być jedyną opcją, gdy kodowanie nie jest znane… Używając iconv, właśnie uruchomiłem wszystkie 1168 kodowań (w tym aliasów) wymienionych iconv -lna jednym z moich plików .htm ... Było 683 kodowań, które przeszły zbieranie. Rzeczywisty zestaw znaków pliku = ISO-8859-1 .. składa się ze wszystkich wartości z jednego paska ASCII-zakres. Znak inny niż ASCII to \ xA9.
Peter.O
0

Również w przypadku, gdy plik -i daje nieznane

Możesz użyć tego polecenia php, które może odgadnąć zestaw znaków, jak poniżej:

W php możesz sprawdzić jak poniżej:

Określając jawnie listę kodowania:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

Dokładniejsze „ mb_list_encodings ”:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"

Tutaj w pierwszym przykładzie widać, że umieściłem listę kodowań (wykryj kolejność list), które mogą być zgodne. Aby uzyskać dokładniejszy wynik, możesz użyć wszystkich możliwych kodowań poprzez: mb_list_encodings ()

Uwaga Funkcje mb_ * wymagają php-mbstring

apt-get install php-mbstring 

Zobacz odpowiedź: https://stackoverflow.com/a/57010566/3382822

Mohamed23gharbi
źródło