在PHP中捕获文件输出(fputcsv)

I'm attempting to capture the output of fputcsv() in order to use gzwrite() to actually write to a tab-delimited file. Basically, I'm querying a database and I want to put these rows into a gzipped CSV file and I'd rather use fputcsv() than actually append "\t" and " " everywhere. Can I somehow do this with output buffering or something similar?

Here's the basic outline of what I have:

$results = get_data_from_db();
$fp = gzopen($file_name, 'w');
if($fp) {
    foreach ($results as $row) {
        ???//something with gzwrite() ?
    }
    gzclose($fp);
}

Thanks!

EDIT: My understanding was that gzwrite() needs to be used to actually write to the file in order for it to actually be gzipped - is this not correct?

Maybe I'm misunderstanding the question but fputcsv() operates on a file handle, which is what gzopen returns, so you can do this:

$results = get_data_from_db();
$fp = gzopen($file_name, 'w');
if($fp) {
    foreach ($results as $row) {
        fputcsv($fp, $row);
    }
    gzclose($fp);
}

I've tested this and it works fine.

You can do it by writing your own stream handler to intercept the writes to the underlying file.

Edit: After reading the spec example 3 on this page sounds like it might be of interest to you

As read on php.net, you could try this little trick:

<?php
// output up to 5MB is kept in memory, if it becomes bigger
// it will automatically be written to a temporary file
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');

fputcsv($csv, array('blah','blah'));

rewind($csv);

// put it all in a variable
$output = stream_get_contents($csv);
?>

This is actually what you tried to avoid (capturing the output), but capturing is a very powerful tool, so why not use it?

Don't forget you can always do this manually without using the csv function without doing anymore work already. I had to do this recently so I could take the same data and either output a CSV as tab delimited, comma delimited or something a browser could display.

All you need to do is use basic arrays and implode (here's a basic example, you need to add some vars to support proper HTMl table output such as column head and tail, row head and tail, etc... but you get the idea:

switch ( $_GET['mode'] )
{
    case "csv":
        $wrapper = "'";
        $delimiter = ",";
        $nextrow = "
";
        break;
    case "txt":
        $wrapper = "";
        $delimiter = "\t";
        $nextrow = "
";
        break;
    case "html":
        $wrapper = "'";
        $delimiter = ",";
        break;
}

$output = array();
$sql = "SELECT * FROM table";
$result = mysql_query($sql);
while ( $row = mysql_fetch_assoc($result) )
{
    $line = array();
    foreach ( $row as $column => $value )
    {
        $line[] = $wrapper . $value . $wrapper;
    }
    $output[] = implode("", $line) . $nextrow;
}

print implode("",$output);