我创建了一个 CSV 文件供我们的客户使用
$output = fopen('php://output', 'w');
并fputcsv()
用于将数据写入客户端下载的 CSV 文件。
我在 Linux 上运行 PHP,因此许多 Windows 应用程序不会解释行尾。
我可以将 CSV 文件写入服务器上的目录,将其读回并执行str_replace()
from \n
to \r\n
,但这似乎是解决问题的一种相当笨拙的方法。有没有办法在不创建物理文件的情况下执行转换?
我创建了一个 CSV 文件供我们的客户使用
$output = fopen('php://output', 'w');
并fputcsv()
用于将数据写入客户端下载的 CSV 文件。
我在 Linux 上运行 PHP,因此许多 Windows 应用程序不会解释行尾。
我可以将 CSV 文件写入服务器上的目录,将其读回并执行str_replace()
from \n
to \r\n
,但这似乎是解决问题的一种相当笨拙的方法。有没有办法在不创建物理文件的情况下执行转换?
您可以使用流过滤器来完成此操作。此示例写入物理文件,但它也应该可以正常工作php://output
。
// filter class that applies CRLF line endings
class crlf_filter extends php_user_filter
{
function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
// make sure the line endings aren't already CRLF
$bucket->data = preg_replace("/(?<!\r)\n/", "\r\n", $bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
// register the filter
stream_filter_register('crlf', 'crlf_filter');
$f = fopen('test.csv', 'wt');
// attach filter to output file
stream_filter_append($f, 'crlf');
// start writing
fputcsv($f, array('1 1', '2 2'));
fclose($f);
不确定您是否可以使用 PHP 本身执行此操作。可能有一种方法可以更改 PHP 的文件写入 EOL,但这可能取决于系统。您没有可以 ping 通的 Windows 系统,是吗?;)
至于一个真正的解决方案,而不是str_replace
逐行,你可以使用 Linux 程序unix2dos
(逆dos2unix
)假设你已经安装了它:
fputcsv($fh ...)
exec("unix2dos " . escapeshellarg($filename));
而不是写入文件,更好的解决方案是使用输出缓冲
function output($buffer) {
return str_replace("\n", "\r\n", $buffer);
}
ob_start('output');
fputcsv(....);
如果在读取 Macintosh 计算机上或由 Macintosh 计算机创建的文件时 PHP 不能正确识别行尾,启用 auto_detect_line_endings 运行时配置选项可能有助于解决问题。ini_set("auto_detect_line_endings", true);