Question

J'utilise fputcsv en PHP pour produire un fichier délimité par des virgules d'une requête de base de données. Lors de l'ouverture du fichier dans gedit dans Ubuntu, il semble correct - chaque enregistrement a un saut de ligne (pas de caractères de saut de ligne visibles, mais vous pouvez dire chaque enregistrement est séparé, et l'ouvrir dans une feuille de calcul OpenOffice me permet de visualiser le fichier correctement.)

Cependant, nous vous envoyons ces fichiers à un client sous Windows et sur leurs systèmes, le fichier est disponible en comme une grande, longue ligne. il l'ouverture dans Excel, il ne reconnaît pas plusieurs lignes du tout.

J'ai lu plusieurs questions ici qui sont assez similaires, y compris celui-ci , qui comprend un lien vers le très instructif Grand schisme Newline explication.

Malheureusement, nous ne pouvons pas simplement dire à nos clients d'ouvrir les fichiers dans un éditeur « plus intelligent ». Ils doivent être en mesure de les ouvrir dans Excel. Est-il possible de programmation pour faire en sorte que les caractères de nouvelle ligne correct sont ajoutés de sorte que le fichier peut être ouvert dans un programme tableur sur un OS?

J'utilise déjà une fonction personnalisée pour forcer des guillemets autour de toutes les valeurs, car fputcsv est sélectif à ce sujet. Je l'ai essayé de faire quelque chose comme ceci:

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

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

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

}

Mais quand le fichier est ouvert dans un éditeur de texte Windows, il apparaît toujours comme une seule longue ligne.

Était-ce utile?

La solution 8

J'a fini par obtenir une réponse plus aux experts-échange; voici ce qui a fonctionné:

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

à utiliser à la place de fputcsv standard.

Autres conseils

// 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);
  }
}

Ceci est une version améliorée de la grande réponse @John Douthat, en préservant la possibilité d'utiliser des délimiteurs et des enceintes et retour sortie d'origine de 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;
}

Utilisation de la fputcsv fonction php écrit uniquement \ n et ne peut pas être personnalisé. Cela rend la fonction sans valeur pour l'environnement Microsoft bien que certains paquets détecteront la nouvelle ligne linux aussi.

Encore les avantages de fputcsv m'a continué de creuser dans une solution pour remplacer le saut de ligne juste avant d'envoyer le fichier. Cela peut être fait en streaming la fputcsv à l'accumulation dans le flux de temp php premier. adapter ensuite le caractère de nouvelles lignes (s) à ce que vous voulez et puis enregistrez le fichier. Comme ceci:

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);

Vous pouvez sortie au format natif unix (\ n uniquement) puis exécutez unix2dos sur le fichier résultant de se convertir à \ r \ n dans les endroits appropriés. Faites juste attention que vos données ne contient pas \ n de. De plus, je vois que vous utilisez un séparateur par défaut de ~. essayez un séparateur par défaut de \ t.

webbiedave signalé (thx!) Probablement la plus propre est d'utiliser un filtre de flux.

Il est un peu plus complexe que d'autres solutions, mais fonctionne même sur les cours d'eau qui ne sont pas modifiables après avoir écrit les (comme un téléchargement en utilisant $handle = fopen('php://output', 'w');)

Voici mon approche:

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);
...

J'ai eu affaire à une situation similaire. Voici une solution que j'ai trouvé que des fichiers CSV sorties avec des fenêtres convivial fins de ligne.

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

Je n'ai pas pu utiliser le depuis que je suis en train de diffuser un fichier au client et ne peut pas utiliser les fseeks.

Windows a besoin \r\n comme linebreak / chariot combo de retour afin de montrer des lignes distinctes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top