PHP не может правильно проанализировать CSV (файл находится в UTF-16LE) - PullRequest
0 голосов
/ 30 сентября 2018

Я пытаюсь проанализировать файл CSV с помощью PHP.
Файл использует запятые в качестве разделителя и двойные кавычки для полей, содержащих запятую (я) , как:

foo,"bar, baz",foo2

Проблема Я сталкиваюсь с тем, что я получаю поля, содержащие запятую (и), разделенные.Я получаю:

  • "2
  • rue du ..."

Вместо: 2, rue du ....


Кодировка:
Файл, кажется, не в UTF8.В начале он имеет странные символы (, очевидно, не BOM , выглядит при конвертации из ASCII в UTF8: ÿþ) и не отображает акценты.

  • Мой кодредактор (Atom) сообщает, что кодировка UTF-16 LE
  • с использованием mb_detect_encoding() в строках CSV возвращает ASCII

Но преобразовать не удается:

  • mb_convert_encoding() преобразует из ASCII, но возвращает азиатские символы из UTF-16LE
  • iconv() возвращает Примечание: iconv (): неправильная кодировка, преобразование из UTF-16LE / ASCII в UTF8 не разрешено .

Синтаксический анализ:
Я попытался проанализировать этот однострочник (см. эти 2 комментария ), используя str_getcsv():

$csv = array_map('str_getcsv', file($file['tmp_name']));

Iзатем попытался с fgetcsv():

$f = fopen($file['tmp_name'], 'r');
while (($l = fgetcsv($f)) !== false) {
    $arr[] = $l;
}
$f = fclose($f);

В обоих случаях я получаю поле адреса в 2 частях.Но когда я пробую этот пример кода, я получаю правильно проанализированные поля:

<code>$str = 'foo,"bar, baz",foo2,azerty,"ban, bal",doe';
$data = str_getcsv($str);
echo '<pre>' . print_r($data, true) . '
';

Подводя итоги с вопросами:

  • Какие символы находятся в начале файла?
  • Как я могу быть уверен вкодировка? (Atom читает файл с UTF-16 LE и вначале не отображает странные символы)
  • Что приводит к сбою функций синтаксического анализа csv?
  • Если мне следует полагатьсячто еще можно использовать для разбора строк CSV?

1 Ответ

0 голосов
/ 01 октября 2018

Я наконец решил это сам:

Я отправил файл на веб-сайты обнаружения кодирования в Интернете, которые возвратили UTF16LE .После проверки того, что такое UTF16LE , он говорит, что имеет BOM (метка порядка байтов) .
В моих предыдущих попытках использовался file(), который возвращает массив строк файла и с fopen(), который возвращает ресурс, но мы все равно анализируем построчно .

РаботающийМне пришло в голову решение о преобразовании всего файла (каждая строка за раз) вместо преобразования каждой строки отдельно.Вот рабочее решение:

$f = file_get_contents($file['tmp_name']);          // Get the whole file as string
$f = mb_convert_encoding($f, 'UTF8', 'UTF-16LE');   // Convert the file to UTF8
$f = preg_split("/\R/", $f);                        // Split it by line breaks
$f = array_map('str_getcsv', $f);                   // Parse lines as CSV data

Я больше не разделяю поля адреса на внутренние запятые.

...