Преобразование кодировки в PHP (ISO-8859-1, UTF-8, CP1250)

Я хочу работать с данными из файла CSV, но понял, что буквы отображаются неправильно. Я пробовал миллион способов конвертировать кодировку, но ничего не работает. Работает на MacOS, PHP 7.4.4.

После выполнения fgets() или fgetcsv() для переменной дескриптора я получу это (например, 2 строки / строки).

Kód ADM;Kód obce;Název obce;Kód MOMC;Název MOMC;Kód MOP;Název MOP;Kód èásti obce;Název èásti obce;Kód ulice;Název ulice;Typ SO;Èíslo domovní;Èíslo orientaèní;Znak èísla orientaèního;PSÈ;Souøadnice Y;Souøadnice X;Platí Od

1234;1234;HorniDolni;;;;;1234;HorniDolni;;;è.p.;2;;;748790401;4799.98;15893971.21;2013-12-01T00:00:00

Это более-менее правильный чешский язык, но буква č заменяется è а также ř заменяется ø, ни один из них не является частью чешского алфавита. Уверен, неуместных букв в файле будет больше.

Выполнение file -I path/to/file я получил file: text/plain; charset=iso-8859-1что печально, потому что что касается вики, эта кодировка не включает чешский алфавит.

Ни одна из следующих команд не преобразовывала неуместные буквы:mb_convert_encoding($line, 'UTF-8', 'ISO8859-1')iconv('ISO-8859-1', 'UTF-8', $line)iconv('ISO8859-1', 'UTF-8', $line)

Я заметил, что в ISO-8859-1 КНИГУø письмо имеет код 00F8. Windows-1250 (который включает чешский аплабет) имеет правильную буквуř с кодом 0159 но им обоим предшествует 00F8. То же с письмомč а также è которым обоим предшествует код 00E7. Я не очень хорошо разбираюсь в кодировке, но кажется, что файл закодирован в Windows-1250, но интерпретатор думает, что это кодировка ISO-8859-1, и берет букву, которая находится на месте / код оригинала.

Но ни одно преобразование (ISO-8859-1 => Windows-1250, ISO-8859-1 => UTF-8 или другое) не работает.

Кто-нибудь знает, как это решить? Спасибо!

1 ответ

Решение

Проблема с 8-битной кодировкой символов в том, что для интерпретации правильной кодовой страницы в основном требуется человеческий интеллект.

Когда ты бежишь fileв файле он может определить, что файл в основном состоит из печатаемых символов, но, поскольку он смотрит только на байты, он не может легко отличить iso-8895-1 от iso-8895-2. Чтобыfile, 0x80 такой же как 0x80.

file может только сказать, что файл является текстовым и, вероятно, iso-8895-* или windows-*, из-за использования 0x80-0xFF. Т.е. не только ASCII.

(Кодировки Unicode, такие как UTF-8 и UTF-16, легче обнаружить по их последовательности байтов или метке порядка байтов, установленной в верхней части файла)

Есть несколько интеллектуальных детекторов кодовых страниц символов, которые с помощью словарей на разных языках могут оценить кодовую страницу на основе последовательностей символов / байтов.

Вероятное преобразование, которое вам нужно, просто iso-8895-2 -> UTF-8.

Для вас важно то, что вы знаете исходную кодировку (интерпретацию), а затем, когда вы ее проверяете, вы точно знаете, в какой кодировке вы ее просматриваете.

Например, PHP по умолчанию устанавливает кодировку HTTP на iso-8895-1. Это означает, что вы вполне можете правильно конвертировать вiso-8895-2, но ваш браузер будет "интерпретировать" как iso-8895-1.

Лучший способ проверить - сохранить файл на диск, а затем использовать текстовый редактор, например VS Code, предварительно настроенный на требуемую кодировку, прежде чем открывать файл.

Если вам нужна дополнительная помощь, вам нужно будет отредактировать свой вопрос, включив в него точный код, который вы используете.

Другие вопросы по тегам