Чтение CSV-файла с неэкранированными вложениями - PullRequest
0 голосов
/ 16 марта 2012

Я читаю файл CSV, но некоторые значения не экранированы, поэтому PHP читает его неправильно.Вот пример плохой линии:

"635", "", "AUBREY R. PHILLIPS (1920-) - пастель с изображением коттеджей в долине реки с крутыми склонами, возможно, в Северном Уэльсе, подписано и датировано 2000 г., в рамке, 66см на 48см. еще один сельский пейзаж под названием verso «Время сбора урожая, Сомерсет», подписано и датировано 87 г., в рамке, 69см на 49см.учился в школе искусств Стоурбриджа »,« 40 »,« 60 »,« WAT »,« Картины, гравюры и акварели »,

Можно увидеть Время сбора урожая, Сомерсет заключено в кавычки, заставляя PHP думать о своем новом значении.

Когда я выполняю print_r () в каждой строке, ломаные строки выглядят так:

Array
(
    [0] =>  635
    [1] =>  
    [2] => AUBREY R. PHILLIPS (1920- ) - Pastel depicting cottages in a steep sided river valley, possibly North Wales, signed and dated 2000, framed, 66cm by 48cm. another of a rural landscape, titled verso Harvest Time
    [3] => Somerset" signed and dated '87
    [4] => framed
    [5] => 69cm by 49cm. (2)  NB - Aubrey Phillips is a Worcestershire artist who studied at the Stourbridge School of Art."
    [6] => 40
    [7] => 60
    [8] => WAT
    [9] => Paintings, prints and watercolours
    [10] => 
)

Что, очевидно, неправильно, так как теперь он содержит гораздо больше элементов массива, чем другие правильные строки.

Вот PHP, который я использую:

$i = 1;
if (($file = fopen($this->request->data['file']['tmp_name'], "r")) !== FALSE) {
    while (($row = fgetcsv($file, 0, ',', '"')) !== FALSE) {
        if ($i == 1){
            $header = $row;
        }else{
            if (count($header) == count($row)){
                $lots[] = array_combine($header, $row);
            }else{
                $error_rows[] = $row;
            }

        }
        $i++;
    }
    fclose($file);
}

Строки с неправильным количеством значений получаютсяв $error_rows, а остальные помещаются в большой массив $lots.

Чтоя могу сделать, чтобы обойти это?Спасибо.

Ответы [ 5 ]

1 голос
/ 16 марта 2012

Если вы можете удалить "в тексте" следующим образом: \ "

и использовать в fgetcsv укажите th escape char

fgetcsv($file, 0, ',', '"','\');
1 голос
/ 16 марта 2012

Если вы знаете, что вы всегда будете получать записи 0 и 1, и что последние 5 записей в массиве всегда будут правильными, так что это просто описательная запись, которая «повреждена» из-за неэкранированных символов вложения, тогда вы можете извлечьпервые 2 и последние 5 с использованием array_slice () , implode () остаток обратно в одну строку (восстановление потерянных кавычек) и правильное восстановление массива.

$testData = '" 635"," ","AUBREY R. PHILLIPS (1920- ) - Pastel depicting cottages in a steep sided river valley, possibly North Wales, signed and dated 2000, framed, 66cm by 48cm. another of a rural landscape, titled verso "Harvest Time, Somerset" signed and dated \'87, framed, 69cm by 49cm. (2) NB - Aubrey Phillips is a Worcestershire artist who studied at the Stourbridge School of Art.","40","60","WAT","Paintings, prints and watercolours",';

$result = str_getcsv($testData, ',', '"');

$hdr = array_slice($result,0,2);
$bdy = array_slice($result,2,-5);
$bdy = trim(implode('"',$bdy),'"');
$ftr = array_slice($result,-5);

$fixedResult = array_merge($hdr,array($bdy),$ftr);
var_dump($fixedResult);

результат:

array
  0 => string ' 635' (length=4)
  1 => string ' ' (length=1)
  2 => string 'AUBREY R. PHILLIPS (1920- ) - Pastel depicting cottages in a steep sided river valley, possibly North Wales, signed and dated 2000, framed, 66cm by 48cm. another of a rural landscape, titled verso Harvest Time" Somerset" signed and dated '87" framed" 69cm by 49cm. (2) NB - Aubrey Phillips is a Worcestershire artist who studied at the Stourbridge School of Art.' (length=362)
  3 => string '40' (length=2)
  4 => string '60' (length=2)
  5 => string 'WAT' (length=3)
  6 => string 'Paintings, prints and watercolours' (length=34)
  7 => string '' (length=0)

Не идеально, но, возможно, достаточно хорошо

Альтернатива состоит в том, чтобы заставить того, кто генерирует CSV, правильно покинуть свои вложения

0 голосов
/ 11 декабря 2014
$csv = explode(' ', $csv);
foreach ($csv as $k => $v) if($v[0] == '"' && substr($v, -1) == '"') {
    $csv[$k] = mb_convert_encoding('“' . substr($v, 1, -1) . '”', 'UTF-8', 'HTML-ENTITIES');
}
$csv = implode(' ', $csv);
$csv = str_getcsv($csv);
0 голосов
/ 16 марта 2012

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

<code><?php
  $csv = file_get_contents("yourfile.csv");
  $lines = split("\r\n", $csv);
  echo "<pre>";
  foreach($lines as $line)
  {
    $line = str_replace("\",\"", "\"@@@\"", $line);
    $fields = split("@@@", $line);
    print_r($fields);
  }
  echo "
";?>
0 голосов
/ 16 марта 2012

Это длинный выстрел, так что не принимайте меня всерьез.

В тексте я увидел шаблон, который у всех ',', которые вы хотите игнорировать, после них есть пробел. Найдите и замените ',' на 'FUU' или что-то уникальное.

Теперь проанализируйте файл CSV. Это может получить правильный формат. Вам нужно только заменить 'FUU' обратно на ','

:)

...