Mám několik .htm
soubory, které se otevírají v Gedit bez varování/chyby, ale když tyto stejné soubory otevřu v Jedit
, upozorní mě na neplatné kódování UTF-8 ...
Značka metadat HTML uvádí "charset = ISO-8859-1". Jedit umožňuje seznam nouzových kódování a seznam kódovacích autodetektorů (v současnosti „kusovník XML-PI“), takže můj okamžitý problém byl vyřešen. Ale to mě přimělo přemýšlet o: Co kdyby tam nebyla meta data?
Pokud informace o kódování prostě nejsou k dispozici, existuje program CLI, který může udělat „nejlepší odhad“, které kódování lze použít?
A i když se jedná o poněkud odlišný problém; Existuje program CLI, který testuje platnost známého kódování?
Příkaz file
dělá „nejlepší odhady“ ohledně kódování. Použijte -i
parametr vynutí file
k tisku informací o kódování.
Demonstrace:
$ 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
Takto jsem vytvořil soubory:
$ echo ä > umlaut-utf8.txt
V dnešní době je vše utf-8. Přesvědčte se však:
$ hexdump -C umlaut-utf8.txt
00000000 c3 a4 0a |...|
00000003
Porovnat s https://en.wikipedia.org/wiki/Ä#Computer_encoding
Převést na další kódování:
$ iconv -f utf8 -t iso88591 umlaut-utf8.txt > umlaut-iso88591.txt
$ iconv -f utf8 -t utf16 umlaut-utf8.txt > umlaut-utf16.txt
Zkontrolujte hexadecimální výpis:
$ hexdump -C umlaut-iso88591.txt
00000000 e4 0a |..|
00000002
$ hexdump -C umlaut-utf16.txt
00000000 ff fe e4 00 0a 00 |......|
00000006
Vytvořte něco „neplatného“ smícháním všech tří:
$ cat umlaut-iso88591.txt umlaut-utf8.txt umlaut-utf16.txt > umlaut-mixed.txt
Co říká file
:
$ 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
Příkaz file
nemá představu o „platném“ nebo „neplatném“. Vidí jen některé bajty a snaží se uhádnout, jaké by mohlo být kódování. Jako lidé bychom mohli být schopni rozpoznat, že soubor je textový soubor s některými přehlásky v „nesprávném“ kódování. Ale jako počítač by potřeboval nějaký druh umělé inteligence.
Dalo by se argumentovat, že heuristika file
je nějaký druh umělé inteligence. Přesto, i když je, je velmi omezený.
Zde je více informací o příkazu file
: http://www.linfo.org/file_command.html
Není vždy možné zjistit, jaké je kódování textového souboru. Například byte sekvence \303\275
(c3 bd
v šestnáctkové soustavě) může být ý
v UTF-8 nebo ý
v latině1 nebo Ă˝
v latině2 nebo 羸
v BIG-5 atd.
Některá kódování mají neplatné bajtové sekvence, takže je možné je určitě vyloučit. To platí zejména pro UTF-8; většina textů ve většině 8bitových kódování není platná UTF-8. Můžete testovat platný UTF-8 pomocí isutf8
od moreutils nebo s iconv -f utf-8 -t utf-8 >/dev/null
, mezi ostatními.
Existují nástroje, které se snaží uhodnout kódování textového souboru. Mohou dělat chyby, ale často pracují v praxi, pokud se je záměrně nechcete oklamat.
file
Encode::Guess
(část standardní distribuce) se pokusí následná kódování na bajtovém řetězci a vrací první kódování, ve kterém je řetězec platný text.Pokud existují metadata (HTML/XML charset=
, TeX \inputenc
, emacs -*-coding-*-
,…) V souboru jsou pokročilí editoři jako Emacs nebo Vim často schopni analyzovat tato metadata. Není však snadné automatizovat z příkazového řádku.
Také v případě, že soubor -i vám dává neznámé
Můžete použít tento příkaz php, který dokáže hádat znakovou sadu takto:
V php se můžete podívat takto:
Výslovná specifikace seznamu kódů:
php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"
Přesnější " mb_list_encodings ":
php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"
Zde v prvním příkladu vidíte, že jsem dal seznam kódování (detekovat pořadí seznamů), které by se mohly shodovat. Pro přesnější výsledek můžete použít všechna možná kódování pomocí: mb_list_encodings ()
Poznámka: Funkce mb_ * vyžadují php-mbstring
apt-get install php-mbstring
Viz odpověď: https://stackoverflow.com/a/57010566/3382822