Краткая история о FEFF, невидимый символ UTF-8, разрушивший наши файлы CSV

kratkaya istoriya o feff nevidimyj simvol utf 8 razrushivshij nashi fajly?v=1656596767

Сегодня мы столкнулись с ошибкой при попытке создать некоторые исходные базы данных из CSV. Этот CSV изначально был сгенерирован мной с помощью скрипта Ruby, передавшего выход в файл и сохранившегося как CSV.

CSV был проверен в Git и использовался некоторое время, пока нам не пришлось обновить некоторые его части, добавив новый столбец и исправив некоторые значения.

Хотя мы не знаем точной причины, моя теория заключается в том, что каким-то образом Excel для Mac (мы все используем Mac) добавил к нему дополнительные метаданные даже после сохранения файла как CSV.

Это, в свою очередь, заставило любой, кто использует семена, получить такую ​​ошибку:

CSV::MalformedCSVError: Illegal quoting in line 1.

Я открыл файл CSV, и ничего подозрительного не смотрелось. Мое первое мнение заключалось в том, что некоторые левые/правые кавычки были каким-то образом смешаны в файле вместо просто «обычных» двойных кавычек: ". Но при дальнейшем расследовании не оказалось ничего необычного. Это заставило меня просто стереть весь файл и фактически ввести первую строчку снова.

Я снова сохранил этот файл и запустил миграцию:

CSV::MalformedCSVError: Illegal quoting in line 1.

Что?

Ладно, это сводило меня с ума. Я открыл новый файл, снова ввел точную одну строку и запустил миграцию. Это сработало. Так что было в том файле?

Только один способ узнать:

cat companies.csv | pbcopy | pbpaste > temp.csv
rm companies.csv
mv temp.csv companies.csv
git diff

Итак, OSX имеет эти две очень полезные функции: pbcopy и pbpaste. В основном все, к чему подключено pbcopy попадает в ваш буфер обмена и pbpaste помещает то, что у вас в буфере обмена, в стандартный выход (stdout). Но это удаляет все форматирование.

Очень полезно, если вы просто хотите скопировать текст откуда-то и хотите вставить его в редактор WYSIWYG без форматирования. Например, когда вы пишете сообщение с Gmail.

Затем я удалил исходный файл и сохранил новый «неформатированный» файл с тем же именем файла, чтобы я мог увидеть разницу.

И наконец мы увидели человека-невидимку:

xkI0eL8SP-nbAV3RKrpq8GdMG09j9HjsgHga
Невидимый персонаж в Bitbucket Atlassian.
iS2g-cMpndutvi-N0lw6dCfwuiFSHbtpeW0o
Настоящее имя невидимого персонажа!

Быстрый поиск в Google сказал нам, что наш друг U+FEFF назывался а ZERO WIDTH NO-BREAK SPACE. Кроме того, скорая поездка в Википедию рассказала нам о фактическом использовании U+FEFFболее известен как Byte order mark или BOM.

Наш друг FEFF означает разные вещи, но в основном это сигнал для программы о том, как читать текст. Это может быть UTF-8 (чаще), UTF-16или даже UTF-32.

FEFF сам для UTF-16 — в UTF-8 он более известен как 0xEF,0xBB, or 0xBF.

Насколько я понимаю, когда файл CSV был открыт в Excel и сохранен, Excel создал место для нашего невидимого безбилетника, U+FEFF. И перед файлом для скачивания!

Excel совершил какую-то магию, и это, вероятно, было сохранено UTF-16 вместо UTF-8. UTF-8 не понимает BOM и просто рассматривает его как несимвол, поэтому визуально файл был в порядке. Но Руби CSV подумал, что что-то не так, потому что он предположил, что читаемый файл был UTF-8 и это не могло игнорировать Mr. U+FEFF.

Итак, урок: не открывайте (и не храните!) файл CSV в Excel, если хотите передать его в Ruby’s CSV парсер.

Если вы когда-нибудь столкнетесь с такой ошибкой, обязательно ищите скрытые символы, не отображаемые вашим редактором. Если вы все еще не видите его и используете OSX, тогда pbcopy и pbpaste поможет вам в этом – они удаляют любое форматирование или скрытые символы из текста в дополнение к его копированию и вставке.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *