Php fputcsv和换行代码

Php fputcsv和换行代码,php,newline,fputcsv,Php,Newline,Fputcsv,我在PHP中使用fputcsv输出数据库查询的逗号分隔文件。在Ubuntu的gedit中打开文件时,它看起来是正确的——每条记录都有一个换行符(没有可见的换行符,但可以看出每条记录是分开的,在OpenOffice电子表格中打开它可以让我正确地查看文件。) 然而,我们将这些文件发送到Windows上的客户端,在他们的系统上,文件以一个大的、长的行的形式出现。在Excel中打开它,它根本无法识别多行 我在这里读到了几个非常相似的问题,包括,其中包括一个链接,指向真正信息丰富的解释 不幸的是,我们不能

我在PHP中使用fputcsv输出数据库查询的逗号分隔文件。在Ubuntu的gedit中打开文件时,它看起来是正确的——每条记录都有一个换行符(没有可见的换行符,但可以看出每条记录是分开的,在OpenOffice电子表格中打开它可以让我正确地查看文件。)

然而,我们将这些文件发送到Windows上的客户端,在他们的系统上,文件以一个大的、长的行的形式出现。在Excel中打开它,它根本无法识别多行

我在这里读到了几个非常相似的问题,包括,其中包括一个链接,指向真正信息丰富的解释

不幸的是,我们不能只告诉客户在“更智能”的编辑器中打开文件。他们需要能够在Excel中打开它们。是否有任何编程方法可以确保添加正确的换行符,以便在任何操作系统上的电子表格程序中打开文件

我已经在使用自定义函数强制在所有值周围加引号,因为fputcsv是有选择性的。我试过这样做:

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

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

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

}

但是,当在Windows文本编辑器中打开文件时,它仍然显示为一个长行。

Windows需要
\r\n
作为换行符/回车组合,以便显示单独的行。

或者,您可以以本机unix格式输出(\n仅限)然后在生成的文件上运行unix2dos,以便在适当的位置\r\n转换为。请注意,您的数据不包含\n。另外,我看到您正在使用默认分隔符~。请尝试使用默认分隔符\t

我一直在处理类似的情况。我发现了一个解决方案,可以输出带有windows友好行结尾的CSV文件


我无法使用,因为我正在尝试将文件流式传输到客户端,无法使用fseeks。

我最终在专家交换中得到了答案;以下是有效的方法:

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

用于替代标准fputcsv。

使用php函数fputcsv仅写入\n,无法自定义。这使得该函数对于microsoft环境毫无价值,尽管有些软件包也会检测到linux新行

尽管如此,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);

这是@John Dou的改进版本,这是一个很好的答案,保留了使用自定义分隔符和附件并返回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;
}
正如所指出的(thx!)可能最干净的方法是使用流过滤器

它比其他解决方案要复杂一点,但甚至可以在写入流后不可编辑的流上工作(例如使用
$handle=fopen('s)下载)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);
...

unix2dos是否可以安装在服务器上并以编程方式调用?因为我必须手动接触这些文件——它们是以编程方式创建的,并以编程方式通过电子邮件发送给客户端。在php中,您可以从语言内部调用程序:谢谢。不幸的是,我刚刚被告知这个网站将以云为主机,所以我无法知道它是否安装了,如果没有安装,我也无法控制它的安装。我需要一种只使用标准php命令的方法来实现这一点。是的,我知道这一点,如果您查看我发布的代码,您将看到我正在将\r\n添加到我正在写入文件的行。这似乎无关紧要-Windows没有这样解读它。+1用于突出显示我遇到的问题,您是否包含您的csv字段标题?将上述代码与公认的解决方案进行比较(假设此文件是在Linux上生成的),看起来原始问题可能是在将文件传输到客户端时,不一定是这一代人。例如,从Linux到Windows,以ASCII模式通过FTP下载原始文件(使用CR+LF EOL),会导致行尾损坏。谢谢!我会试一试,看看是否有帮助。我知道这是一个古老的答案,但如果我没有提到这是一个来自专家交流的糟糕答案,那我就是失职了。它甚至不处理双引号转义。请改用流过滤器。这就是他们在那里的原因。谢谢分享这个商店导入!明亮的短,比任何其他解决方案都好,这是一个很好的答案!我在下面发布了一个改进的版本,保留了使用自定义分隔符和附件的可能性,并返回fputcsv的原始输出这里是什么$handle?@MiomirDancevic这是一个使用fopen()函数创建的资源
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);
...