32

PHP で fputcsv を使用して、データベース クエリのコンマ区切りファイルを出力しています。Ubuntu の gedit でファイルを開くと、正しく表示されます。各レコードには改行があります (改行文字は表示されませんが、各レコードが区切られていることがわかります。OpenOffice スプレッドシートで開くと、ファイルを正しく表示できます。)

ただし、これらのファイルを Windows 上のクライアントに送信すると、クライアントのシステムでは、ファイルが 1 つの大きな長い行として受信されます。Excelで開くと、複数行がまったく認識されません。

ここには、非常に有益な Great Newline Schismの説明へのリンクが含まれているthis oneなど、かなり似ている質問がいくつかあります。

残念ながら、クライアントに「よりスマートな」エディターでファイルを開くように指示することはできません。それらを Excel で開くことができる必要があります。任意の OS のスプレッドシート プログラムでファイルを開くことができるように、正しい改行文字が追加されていることを確認するプログラム的な方法はありますか?

fputcsvはそれについて選択的であるため、私はすでにカスタム関数を使用してすべての値を強制的に引用しています。私はこのようなことを試みました:

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

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

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

}

ただし、ファイルを Windows テキスト エディターで開くと、依然として 1 行の長い行として表示されます。

4

8 に答える 8

42
// 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);
  }
}
于 2011-11-01T00:10:16.193 に答える
6

php関数を使用すると、fputcsvは\ nのみを書き込み、カスタマイズすることはできません。これにより、一部のパッケージはLinuxの改行も検出しますが、この機能はMicrosoft環境では無価値になります。

それでも、fputcsvの利点により、ファイルに送信する直前に改行文字を置き換えるソリューションを掘り下げていました。これは、最初にfputcsvをビルドインphp一時ストリームにストリーミングすることで実行できます。次に、改行文字を必要なものに適合させてから、ファイルに保存します。このような:

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);
于 2011-03-11T09:19:05.940 に答える
4

webbiedave指摘したように (thx!)、おそらく最もクリーンな方法は、ストリーム フィルターを使用することです。

他のソリューションよりも少し複雑ですが、書き込み後に編集できないストリームでも機能します (を使用したダウンロードなど$handle = fopen('php://output', 'w');) 。

これが私のアプローチです:

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);
...
于 2015-01-16T13:57:25.070 に答える
2

または、ネイティブのUNIX形式(\ nのみ)で出力してから、結果のファイルに対してunix2dosを実行して、適切な場所で\ r\nに変換することもできます。データに\nが含まれていないことに注意してください。また、デフォルトの区切り文字〜を使用しているようです。\tのデフォルトの区切り文字を試してください。

于 2010-11-02T17:41:05.297 に答える
1

私は同様の状況に対処してきました。これは、Windowsに適した行末でCSVファイルを出力することがわかったソリューションです。

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

ファイルをクライアントにストリーミングしようとしていて、fseek を使用できないため、 を使用できませんでした。

于 2010-11-10T00:43:57.403 に答える
-1

ウィンドウは、別の行を表示するために、改行/キャリッジリターン コンボ\r\nとして必要です。

于 2010-11-02T17:37:26.703 に答える
-3

私は最終的に専門家交換で答えを得ました。これが機能したものです:

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

標準の fputcsv の代わりに使用されます。

于 2010-11-16T18:27:52.003 に答える