2012-03-16 2 views
0

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

«635»,»„“AUBREY Р. Филлипс (1920-) - Пастель изображающей коттеджи в крутой сторонняя долина реки, возможно, Северный Уэльс, подписанный и датирован 2000, обрамлен, 66 см на 48 см. другой деревенский пейзаж, названный verso «Время сбора урожая, Сомерсет», подписанное и датированное 1987 годом, в рамке, 69 см на 49 см. (2) NB - Обри Филлипс - художник Вустершира который учился в Stourbridge школа искусств. "" 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 массив.

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

+1

Если разместить свой код, как вы проанализируйте CSV, там могут быть ошибки, но не могу не сказать вам, что без вашего кода. – Churk

+0

@Churkm Done :) – 472084

ответ

1

Если вы знаете, что вы всегда будете получать записи 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

Это кажется немного взломанным, но если это единственный способ. Надеюсь, я не получу «поврежденные» данные в других областях LOL! Одна небольшая проблема, ваша содержит «названный verso Harvest Time» Somerset «подписанный и датированный», когда оригинал «назван verso» «Время урожая, Сомерсет» подписан и датирован – 472084

+0

Вот почему я добавил «Не идеально, но, возможно, достаточно хорошо» –

0

Это длинный выстрел, поэтому я не отношусь серьезно.

Я видел шаблон в тексте, в котором все «,» вы хотите игнорировать, имеет пробел после него. Поиск и замена «,» на «FUU» или что-то уникальное.

Теперь проанализируйте файл csv. Он может получить правильный формат. Вам нужно всего лишь заменить «Фуу» обратно в «»

:)

0

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

<?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 "</pre>"; 
?> 
+0

Я редактировал свой Q с помощью PHP, который я использую сейчас – 472084

1

Если вы можете ecape «в тексте, как это: \»

и в fgetcsv использования указать й побег полукокса

fgetcsv($file, 0, ',', '"','\'); 
0
$csv = explode(' ', $csv); 
foreach ($csv as $k => $v) if($v[0] == '"' && substr($v, -1) == '"') { 
    $csv[$k] = mb_convert_encoding('&ldquo;' . substr($v, 1, -1) . '&rdquo;', 'UTF-8', 'HTML-ENTITIES'); 
} 
$csv = implode(' ', $csv); 
$csv = str_getcsv($csv); 
Смежные вопросы