php fputcsv 和换行代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4080456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
fputcsv and newline codes
提问by EmmyS
I'm using fputcsv in PHP to output a comma-delimited file of a database query. When opening the file in gedit in Ubuntu, it looks correct - each record has a line break (no visible line break characters, but you can tell each record is separated,and opening it in OpenOffice spreadsheet allows me to view the file correctly.)
我在 PHP 中使用 fputcsv 输出数据库查询的逗号分隔文件。在 Ubuntu 的 gedit 中打开文件时,它看起来是正确的 - 每条记录都有一个换行符(没有可见的换行符,但您可以看出每条记录是分开的,在 OpenOffice 电子表格中打开它可以让我正确查看文件。)
However, we're sending these files on to a client on Windows, and on their systems, the file comes in as one big, long line. Opening it in Excel, it doesn't recognize multiple lines at all.
但是,我们将这些文件发送到 Windows 上的客户端,在他们的系统上,该文件以一大长串的形式出现。在 Excel 中打开它,它根本无法识别多行。
I've read several questions on here that are pretty similar, including this one, which includes a link to the really informative Great Newline Schismexplanation.
我在这里阅读了几个非常相似的问题,包括这个问题,其中包含一个链接,指向真正信息丰富的Great Newline Schism解释。
Unfortunately, we can't just tell our clients to open the files in a "smarter" editor. They need to be able to open them in Excel. Is there any programmatic way to ensure that the correct newline characters are added so the file can be opened in a spreadsheet program on any OS?
不幸的是,我们不能只是告诉我们的客户在“更智能”的编辑器中打开文件。他们需要能够在 Excel 中打开它们。是否有任何编程方法可以确保添加正确的换行符,以便可以在任何操作系统上的电子表格程序中打开文件?
I'm already using a custom function to force quotes around all values, since fputcsv is selective about it. I've tried doing something like this:
我已经在使用自定义函数来强制在所有值周围加上引号,因为 fputcsv 对此有选择性。我试过做这样的事情:
function my_fputcsv($handle, $fieldsarray, $delimiter = "~", $enclosure ='"'){
$glue = $enclosure . $delimiter . $enclosure;
return fwrite($handle, $enclosure . implode($glue,$fieldsarray) . $enclosure."\r\n");
}
But when the file is opened in a Windows text editor, it still shows up as a single long line.
但是当文件在 Windows 文本编辑器中打开时,它仍然显示为一个长行。
采纳答案by EmmyS
I did eventually get an answer over at experts-exchange; here's what worked:
我最终在专家交流中得到了答案;这是有效的:
function my_fputcsv($handle, $fieldsarray, $delimiter = "~", $enclosure ='"'){
$glue = $enclosure . $delimiter . $enclosure;
return fwrite($handle, $enclosure . implode($glue,$fieldsarray) . $enclosure.PHP_EOL);
}
to be used in place of standard fputcsv.
用于代替标准 fputcsv。
回答by John Douthat
// 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);
}
}
回答by lucaferrario
This is an improved version of @John Douthat's great answer, preserving the possibility of using custom delimiters and enclosures and returning fputcsv's original output:
这是@John Douthat 很好的答案的改进版本,保留了使用自定义分隔符和附件并返回 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;
}
回答by Bob Siefkes
Using the php function fputcsv writes only \n and cannot be customized. This makes the function worthless for microsoft environment although some packages will detect the linux newline also.
使用php函数fputcsv只能写\n,不能自定义。这使得该功能对于 microsoft 环境毫无价值,尽管某些软件包也会检测到 linux 换行符。
Still the benefits of fputcsv kept me digging into a solution to replace the newline character just before sending to the file. This can be done by streaming the fputcsv to the build in php temp stream first. Then adapt the newline character(s) to whatever you want and then save to file. Like this:
fputcsv 的好处仍然让我深入研究在发送到文件之前替换换行符的解决方案。这可以通过首先将 fputcsv 流式传输到 php temp 流中的构建来完成。然后将换行符调整为您想要的任何内容,然后保存到文件。像这样:
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);
回答by Torge
As webbiedavepointed out (thx!) probably the cleanest way is to use a stream filter.
正如webbiedave指出的那样(谢谢!)可能最干净的方法是使用流过滤器。
It is a bit more complex than other solutions, but even works on streams that are not editable after writing to them (like a download using $handle = fopen('php://output', 'w');
)
它比其他解决方案稍微复杂一些,但即使在写入后不可编辑的流上也能工作(例如使用 下载$handle = fopen('php://output', 'w');
)
Here is my approach:
这是我的方法:
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/', "\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);
...
回答by Zak
alternatively, you can output in native unix format (\n only) then run unix2dos on the resulting file to convert to \r\n in the appropriate places. Just be careful that your data contains no \n's . Also, I see you are using a default separator of ~ . try a default separator of \t .
或者,您可以以本机 unix 格式(仅限 \n)输出,然后在生成的文件上运行 unix2dos 以在适当的位置转换为 \r\n。请注意您的数据不包含 \n's 。另外,我看到您使用的是默认分隔符 ~ 。尝试使用 \t 的默认分隔符。
回答by PPC-Coder
I've been dealing with a similiar situation. Here's a solution I've found that outputs CSV files with windows friendly line-endings.
我一直在处理类似的情况。这是我发现的一个解决方案,它输出带有 Windows 友好行尾的 CSV 文件。
http://www.php.net/manual/en/function.fputcsv.php#90883
http://www.php.net/manual/en/function.fputcsv.php#90883
I wasn't able to use the since I'm trying to stream a file to the client and can't use the fseeks.
我无法使用 ,因为我正在尝试将文件流式传输到客户端并且无法使用 fseeks。
回答by Zak
windows needs \r\n
as the linebreak/carriagereturn combo in order to show separate lines.
windows 需要\r\n
作为换行符/回车符组合来显示单独的行。