Разница между Control.Invoke()
и Control.BeginInvoke()
состоит в том, что
BeginInvoke()
запланирует асинхронное действие в потоке GUI. Когда запланировано асинхронное действие, ваш код продолжается. Некоторое время спустя (вы точно не знаете, когда) ваше асинхронное действие будет выполнено Invoke()
выполнит ваше асинхронное действие (в потоке GUI) и будет ждать, пока ваше действие не будет завершено. Логический вывод заключается в том, что делегат, который вы передаете в Invoke()
, может иметь out-параметры или возвращаемое значение, в то время как делегат, который вы передаете в BeginInvoke()
, не может (вы должны использовать EndInvoke для получения результатов ).
// 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);
}
}
Использование функции 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);
Как отметил 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 с оконными дружескими окончаниями.
http://www.php.net/manual/en/function.fputcsv.php#90883
Я не смог использовать, поскольку я пытаюсь Потоковая передача файла клиенту и не может использовать fseeks.
windows нуждается в \r\n
как возврат строки / возврат каретки для отображения отдельных строк.