Cómo analizar csv en PHP con datos de varias líneas en una columna

3 minutos de lectura

Considere un archivo CSV como este

item1,"description 1"
item2,"description 2"
item3,"description 3
description 3 continues on new line"
item4,"description 4"

que debe analizarse así

item1,"description 1"
item2,"description 2"
item3,"description 3 description 3 continues on new line"
item4,"description 4"

¿Hay alguna forma de analizar este CSV en PHP que tiene valores de varias líneas?

  • @goreSplatter, o simplemente use uno existente.

    – Bart Kiers

    19 de enero de 2011 a las 8:18

  • @Bart Lo siento, omití la otra solución obvia.

    – Linus Klein

    19 de enero de 2011 a las 8:21

  • posible duplicado del archivo parse csv php

    – fuera

    26 de diciembre de 2011 a las 7:36

Aquí hay algunos ejemplos prácticos de cómo hacerlo. Estoy usando fgetcsv:

CSV en variable de cadena $CsvString:

$fp = tmpfile();
fwrite($fp, $CsvString);
rewind($fp); //rewind to process CSV
while (($row = fgetcsv($fp, 0)) !== FALSE) {
    print_r($row);
}

CSV en el archivo:

if (($handle = fopen("test.csv", "r")) !== FALSE) {
  while (($row = fgetcsv($handle, 0, ",")) !== FALSE) {
    print_r($row);
  }
  fclose($handle);
}

  • Excelente respuesta Tengo CSV cargados por el usuario con \r finales de línea (no tengo idea de por qué), y tuve que reemplazarlos antes de analizar CSV. Dado que str_getcsv no maneja varias líneas, y algunas filas tienen líneas nuevas, esto (aunque es un poco complicado, poner cosas en un archivo temporal solo para que PHP lo analice) funciona.

    – csga5000

    30 mayo 2015 a las 21:30

fgetcsv debería ser capaz de analizar correctamente esto.
De todos modos, no recomendaría hacer esto a mano, hay muchos errores de este tipo al analizar CSV.

  • El problema es que estaba usando fgets leer la línea del archivo y luego str_getcsv para analizar la cadena en lugar de usar solo fgetcsv. Funcionaba bien con columnas de una sola línea pero no con columnas de varias líneas. Incluso PHP.net difícil dice que fgetcsv “Obtiene la línea del archivo” parece que la “línea” aquí no es una línea real en un archivo de texto sin formato, sino toda la fila real con todos los datos de varias líneas.

    – Ergec

    19 de enero de 2011 a las 12:50

  • Me encontré con el mismo problema hoy e hice un poco pruebaque prueba su afirmación sobre líneas refiriéndose a csv-filas y no real líneas de archivo.

    – Raúl

    25 de marzo de 2013 a las 12:22


  • esperaba usar str_getcsv ya que no tiene que cargar todo el archivo en la memoria, solo la fila que está en rojo. fgetcsv funciona con campos CSV de varias líneas, pero str_getcsv aparentemente no lo hace.

    – Erfán

    19 de diciembre de 2018 a las 3:33


  • @Erfan fgetcsv ¡También solo lee una línea a la vez desde un identificador de archivo abierto…!?

    – deceze

    19 de diciembre de 2018 a las 6:26

avatar de usuario
oriadam

Basado en la respuesta de StanleyD, pero usando un bloque de memoria temporal (en lugar de escribir en el disco) para un mejor rendimiento:

$fp = fopen('php://temp','r+');
fwrite($fp, $CsvString);
rewind($fp); //rewind to process CSV
while (($row = fgetcsv($fp, 0)) !== FALSE) {
    print_r($row);
}

Aquí hay una solución rápida y fácil usando la función PHP str_getcsv()

Aquí hay un ejemplo:

function parse_csv( $filename_or_text, $delimiter=",", $enclosure=""", $linebreak="\n" )
{
    $return = array();
    
    if(false !== ($csv = (filter_var($filename_or_text, FILTER_VALIDATE_URL) ? file_get_contents($filename_or_text) : $filename_or_text)))
    {
        $csv = trim($csv);
        $csv = mb_convert_encoding($csv, 'UTF-16LE');   
        
        foreach(str_getcsv($csv, $linebreak, $enclosure) as $row){
            $col = str_getcsv($row, $delimiter, $enclosure);
            $col = array_map('trim', $col);
            $return[] = $col;
        }
    }
    else
    {
        throw new \Exception('Can not open the file.');
        $return = false;
    }
    
    return $return;
}

Imagine una situación en la que necesita una función que funcione tanto con URL como con texto delimitado por comas. Esta es exactamente la función que funciona así. Simplemente inserte una URL CSV o texto separado por comas y funcionará muy bien.

¿Ha sido útil esta solución?