Сьогодні ми зіткнулися з помилкою під час спроби створити насіння бази даних із 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.
Потім я вилучив оригінальний файл і зберіг новий «неформатований» файл з тим самим іменем, щоб я міг побачити різницю.
І нарешті ми побачили людину-невидимку:


Швидкий пошук у 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
і не могла ігнорувати пана U+FEFF
.
Отже, отриманий урок: не відкривайте (і не зберігайте!) Файл CSV в Excel, якщо ви хочете подати його на CSV
парсер Ruby .
Якщо ви коли-небудь стикалися з такою помилкою, обов’язково шукайте приховані символи, не показані вашим редактором. Якщо ви все ще не можете його побачити і використовуєте OSX, тоді pbcopy
і pbpaste
допоможуть вам - вони видаляють будь-яке форматування або приховані символи з тексту на додаток до копіювання та вставки.