Я пытаюсь проанализировать CSV-файл в PHP через SplFileObject
, грустно SplFileObject
иногда зависает, если в тексте есть ошибочные невидимые символы. Функция обнаруживает кавычку вместо того, чтобы пропустить или прочитать ее как обычный символ, перебирая строки в файле csv.
Снимок экрана ниже взят из Textwrangler:
Я также скопировал это из Textwrangler здесь (невидимый символ должен быть между «forgé.» И «Circa»):
Fer forgé.� Circa
Мой код (часть SplFileObject):
$splFile = new \SplFileObject($file);
$splFile->setFlags(\SplFileObject::DROP_NEW_LINE | \SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD | \SplFileObject::READ_CSV);
$splFile->setCsvControl(",", '"', '"');
Я попытался выяснить, какая кодировка имеет файл CSV через file -I my.csv
, Выход: my.csv: application/octet-stream; charset=binary
, Это странный результат, так как файл читается через Textwrangler и поэтому НЕ двоичный файл. Я также прочитал другой CSV, сгенерированный таким же образом, и результат, как и ожидалось: second.csv: text/plain; charset=utf-8
, Инструмент, используемый для генерации CSV-файлов, называется Visual Web Ripper (инструмент для сканирования веб-страниц).
Как я могу определить, каким символом является этот перевернутый вопросительный знак (кажется, это не испанский перевернутый вопросительный знак — возможно, это просто заполнитель, вставленный Textwrangler)?
Как я могу удалить этот символ и все «недопустимые» символы в моем CSV-файле? Существует ли регулярное выражение, которое соответствует каждому символу, числу, знаку (пунктуации и другим текстовым символам), которое на самом деле является реальным символом и не учитывает что-то подобное в примере выше? Я ищу регулярное выражение, безопасное для Unicode (необходимо также сохранить символы немецкого языка, французские, русские, китайские, японские и корейские). В качестве альтернативы: Как я могу конвертировать CSV-файл с charset=binary
в UTF-8,?
Редактировать:
Если я открою его через nano
редактор это показывает forgé.^@ Circa
, После быстрого поиска это, кажется, символ NUL или \ u0000 (см. Комментарии и https://en.wikipedia.org/wiki/Null_character для справки).
Изменить 2:
Я немного углубился в это: кажется, что есть проблема с $splFile->current()
функция, которая читает строку в текущем указателе файла. Строка обрезается после NUL
характер (независимо от того, пытаюсь ли я прочитать его через SplFileObject::READ_CSV
или просто как обычная строка (без SplFileObject::READ_CSV
параметр)).
Решение состояло в том, чтобы опустить SplFileObject::DROP_NEW_LINE
параметр. Я также проверил, если NUL
символ присутствует: он присутствует, но теперь считается частью текстового значения определенного столбца в csv и является НЕ определяется как цитата или вложение столбца.
Конечно, теперь вы должны отфильтровать пустые строки самостоятельно с помощью f. е. что-то вроде:
$splFileObject = new \SplFileObject();
$splFileObject->setFlags(\SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD | \SplFileObject::READ_CSV);
$columns = $splFileObject->current();
if (count($columns) === 1 && array_key_exists(0, $columns) && $columns[0] === NULL) {
// empty csv line
}
Других решений пока нет …