UTF-8 и BOM в CSV: как отличить кодировку от невидимого префикса
Как проверить UTF-8 BOM, ошибку INVALID_CSV_UTF8 и уже испорченную кириллицу без обещания автоматической перекодировки.
Когда вместо кириллицы видны нечитаемые символы или имя первой колонки неожиданно не совпадает с ожидаемым, проверьте две разные причины: кодировку байтов и префикс BOM. Добавить BOM недостаточно, чтобы превратить Windows-1251 в UTF-8; удалить его недостаточно, чтобы восстановить уже испорченный текст.
В Neraviko CSV → JSON принимает корректный UTF-8. Он умеет снять UTF-8 BOM в начале текста, но не содержит выбора исходной кодовой страницы и не выполняет автоматическую перекодировку произвольного файла.
Что именно означает BOM
UTF-8 BOM — последовательность байтов EF BB BF в самом начале потока. В UTF-8 это сигнатура; порядок байтов она не меняет. Некоторые потребители ожидают её, другие — нет. Unicode FAQ: UTF и BOM, проверено 05.10.2026; дата публикации страницы не указана.
Байты BOM нужно отличать от похожих видимых символов . Последние могут быть следствием неправильного декодирования и повторного сохранения. По одному снимку текста нельзя надёжно определить, какие байты лежат в исходном файле. Сохраните оригинал и уточните экспортную кодировку у отправителя.
Открытый в редакторе файл и вставленный в веб-форму текст — тоже разные этапы. К моменту вставки байты уже могли пройти декодирование в редакторе. Если оно было неверным, CSV-конвертер получает испорченные Unicode-символы, а не оригинальные байты старой кодировки.
Проверенный пример UTF-8 BOM
Синтетический файл состоит из BOM, заголовка name и значения Ёж. Его начало в шестнадцатеричном виде:
EF BB BF 6E 61 6D 65 0A D0 81 D0 B6
В CSV → JSON используйте header=true, delimiter=comma, pretty=false, trailing_newline=false. Ожидаемый результат:
[{"name":"Ёж"}]
Метаданные операции csv.to_json содержат bom_removed=true. Пример выполнен прямым локальным вызовом версии 1 с указанными байтами. Ключ объекта — ровно name, без начального U+FEFF.
Без BOM тот же корректный UTF-8 даёт такой же JSON, но bom_removed=false. Это проверено отдельно. Поддержка BOM не означает, что конвертер должен добавлять его в полученный JSON.
Что происходит с другой кодировкой
Синтетический вход name, LF, затем одиночный байт C6 не является корректным UTF-8. Прямой вызов операции возвращает INVALID_CSV_UTF8. Отказ не угадывает, какой символ хотел записать автор. В рабочем файле сначала нужно правильно декодировать исходную кодировку и сохранить UTF-8.
Воспользуйтесь функцией перекодировки существующего редактора или экспортёра. Укажите известную исходную кодировку и UTF-8 как целевую; затем сравните несколько характерных слов с оригиналом. Не переименовывайте файл и не ограничивайтесь добавлением трёх байтов: это не меняет кодировку остального содержимого.
После перекодировки проверьте разделитель и кавычки. Корректный UTF-8 может содержать неправильный CSV; эти проверки независимы. И наоборот, правильно расположенные запятые не подтверждают, что кириллица прочитана верно.
Если символы уже заменены
Сохранённые вопросительные знаки или replacement character не содержат информации о первоначальных буквах. Конвертер может успешно разобрать такую строку, потому что полученный текст синтаксически корректен. Успех означает успешный разбор нынешних символов, а не восстановление исходных.
Для ремонта нужна оригинальная выгрузка, резервная копия или достоверный источник значений. Не заменяйте «похожие» буквы вручную в идентификаторах и именах: визуально одинаковые символы могут иметь разные кодовые точки. Сверяйте конкретные ключи, а не только общий вид таблицы.
Приёмка после исправления
- Оригинальный файл сохранён, кодировка экспортёра известна.
- Несколько слов с кириллицей совпадают с источником.
- Имя первой колонки не содержит неожиданного префикса.
- JSON содержит ожидаемые Unicode-символы и число записей.
- Целевой импортёр проверен на том же маленьком наборе.
- BOM добавляется или удаляется по его контракту, а не автоматически для всех файлов.
Neraviko ограничивает запрос 262 144 байтами, поля — 65 536 байтами, ширину — 256 колонками. Парсер принимает до 5 000 записей вместе с заголовком. Обработка серверная; сырые входы и выходы по контракту операции не сохраняются и не логируются по умолчанию. Для проверки кириллицы используйте искусственные значения.