Domanda

Sto usando fputcsv in PHP per produrre un file delimitato da virgole di una query di database. Quando si apre il file in gedit in Ubuntu, sembra corretto - ogni record ha un'interruzione di linea (non sono visibili i caratteri di interruzione di riga, ma si può dire ogni record è separato, e aprendolo in OpenOffice foglio di calcolo mi permette di visualizzare il file correttamente.)

Tuttavia, stiamo inviando questi file a un client su Windows, e sui loro sistemi, il file viene in come una grande, lunga fila. L'apertura in Excel, non riconosce più righe a tutti.

Ho letto alcune domande qui che sono abbastanza simili, tra cui questo , che comprende un link alla informativa davvero Grande Scisma Newline spiegazione.

Purtroppo, non possiamo dire ai nostri clienti di aprire i file in un editor di "più intelligente". Hanno bisogno di essere in grado di aprirli in Excel. C'è un modo programmatico per garantire che i caratteri di nuova riga corretti vengono aggiunti in modo che il file può essere aperto in un foglio di calcolo su qualsiasi sistema operativo?

Sono già utilizzando una funzione personalizzata per imporre le virgolette attorno tutti i valori, in quanto fputcsv è selettiva su di esso. Ho provato a fare qualcosa di simile:

function my_fputcsv($handle, $fieldsarray, $delimiter = "~", $enclosure ='"'){

        $glue = $enclosure . $delimiter . $enclosure;

    return fwrite($handle, $enclosure . implode($glue,$fieldsarray) . $enclosure."\r\n");

}

Ma quando il file viene aperto in un editor di testo di Windows, mostra ancora come una singola linea lunga.

È stato utile?

Soluzione 8

ho avuto alla fine ottenere una risposta oltre a esperti di scambio; ecco cosa ha funzionato:

function my_fputcsv($handle, $fieldsarray, $delimiter = "~", $enclosure ='"'){
   $glue = $enclosure . $delimiter . $enclosure;
   return fwrite($handle, $enclosure . implode($glue,$fieldsarray) . $enclosure.PHP_EOL);
}

per essere utilizzato al posto di fputcsv standard.

Altri suggerimenti

// Writes an array to an open CSV file with a custom end of line.
//
// $fp: a seekable file pointer. Most file pointers are seekable, 
//   but some are not. example: fopen('php://output', 'w') is not seekable.
// $eol: probably one of "\r\n", "\n", or for super old macs: "\r"
function fputcsv_eol($fp, $array, $eol) {
  fputcsv($fp, $array);
  if("\n" != $eol && 0 === fseek($fp, -1, SEEK_CUR)) {
    fwrite($fp, $eol);
  }
}

Questa è una versione migliorata del grande risposta di @ John Douthat, preservando la possibilità di utilizzare delimitatori personalizzati e le recinzioni e la restituzione di uscita originale fputcsv:

function fputcsv_eol($handle, $array, $delimiter = ',', $enclosure = '"', $eol = "\n") {
    $return = fputcsv($handle, $array, $delimiter, $enclosure);
    if($return !== FALSE && "\n" != $eol && 0 === fseek($handle, -1, SEEK_CUR)) {
        fwrite($handle, $eol);
    }
    return $return;
}

Con la funzione di php fputcsv scrive solo \ n e non può essere personalizzato. Questo rende la funzione inutile per l'ambiente Microsoft, anche se alcuni pacchetti in grado di rilevare il ritorno a capo Linux.

Ancora i vantaggi di fputcsv mi ha tenuto a scavare in una soluzione per sostituire il carattere di nuova riga appena prima di inviare il file. Questo può essere fatto in streaming il fputcsv per l'accumulo nel flusso di temperatura php prima. Poi adattare il carattere di nuova riga (s) a tutto ciò che si desidera e poi su Salva per file. In questo modo:

function getcsvline($list,  $seperator, $enclosure, $newline = "" ){
    $fp = fopen('php://temp', 'r+'); 

    fputcsv($fp, $list, $seperator, $enclosure );
    rewind($fp);

    $line = fgets($fp);
    if( $newline and $newline != "\n" ) {
      if( $line[strlen($line)-2] != "\r" and $line[strlen($line)-1] == "\n") {
        $line = substr_replace($line,"",-1) . $newline;
      } else {
        // return the line as is (literal string)
        //die( 'original csv line is already \r\n style' );
      }
    }

        return $line;
}

/* to call the function with the array $row and save to file with filehandle $fp */
$line = getcsvline( $row, ",", "\"", "\r\n" );
fwrite( $fp, $line);

unix2dos In alternativa, è possibile output in formato UNIX nativo (\ n solo) quindi eseguito sul file risultante da convertire in \ r \ n nei luoghi appropriati. Basta essere attenti che i vostri dati non contiene \ n di. Inoltre, vedo che si sta utilizzando un separatore di default di ~. provare un separatore predefinito di \ t.

webbiedave rilevare (thx!) Probabilmente il modo più pulito è quello di utilizzare un filtro flusso.

E 'un po' più complesso rispetto ad altre soluzioni, ma funziona anche sui flussi che non sono modificabili dopo la scrittura a loro (come un download utilizzando $handle = fopen('php://output', 'w');)

Ecco il mio approccio:

class StreamFilterNewlines extends php_user_filter {
    function filter($in, $out, &$consumed, $closing) {

        while ( $bucket = stream_bucket_make_writeable($in) ) {
            $bucket->data = preg_replace('/([^\r])\n/', "$1\r\n", $bucket->data);
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}

stream_filter_register("newlines", "StreamFilterNewlines");
stream_filter_append($handle, "newlines");

fputcsv($handle, $list, $seperator, $enclosure);
...

ho avuto a che fare con una situazione simile. Ecco una soluzione che ho trovato che emette i file CSV con le finestre amichevole line-finali.

http://www.php.net/manual/en/ function.fputcsv.php # 90883

Non è stato in grado di utilizzare il dato che sto cercando di trasmettere un file al cliente e non può utilizzare il fseeks.

Windows ha bisogno \r\n come il interruzione di riga / trasporto combo ritorno al fine di mostrare linee separate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top