Вопрос

Я использую fputcsv в PHP для вывода файла запроса к базе данных, разделенного запятыми.При открытии файла в gedit в Ubuntu он выглядит корректно - каждая запись имеет разрыв строки (никаких видимых символов разрыва строки, но вы можете сказать, что каждая запись разделена, и открытие ее в электронной таблице 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, он по-прежнему отображается в виде одной длинной строки.

Это было полезно?

Решение 8

Я в конечном итоге получил ответ на экспертов-обмен; Вот что работает:

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

Для использования вместо стандартных FPUTCSV.

Другие советы

// 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);
  }
}

Это улучшенная версия отличного ответа @john Douthat, сохраняя возможность использования пользовательских разделителей и корпусов и возврата оригинального вывода FPTCSV:

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;
}

Используя функцию php, fputcsv записывает только и не может быть настроен.Это делает функцию бесполезной для среды 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);

В качестве альтернативы вы можете выводить в нативном формате Unix (только N), а затем запустите Unix2dos в полученном файле для преобразования в r n в соответствующие места. Просто будьте осторожны, что ваши данные не содержат нет. Кроме того, я вижу, что вы используете разделитель по умолчанию ~. Попробуйте разделитель по умолчанию T.

Так как 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);
...

Я имел дело с иной ситуацией. Вот решение, которое я обнаружил, что выводит файлы CSV с помощью линейных окончаний Windows.

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

Я не смог использовать с тех пор, как я пытаюсь транслировать файл клиенту и не может использовать FSEEKS.

Вас нужды \r\n как то Линейный разрыв / перевозка Вернуть комбинацию, чтобы показать отдельные строки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top