Я знаю, что это должно звучать глупо ... но редко бывает.
Проверьте, пытаетесь ли вы выполнить php из
**http://localhost/info.php**
, а не из
file:///var/www/info.php
ps> вы можете заметить, что если вы пишете из shell
php info.php
, то ответьте на код (это означает php-функции) ..
Почему бы не использовать объект FileStream?
public void SaveStreamToFile(string fileFullPath, Stream stream)
{
if (stream.Length == 0) return;
// Create a FileStream object to write a stream to a file
using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
{
// Fill the bytes[] array with the stream data
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
// Use FileStream object to write to the specified file
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
}
//If you don't have .Net 4.0 :)
public void SaveStreamToFile(Stream stream, string filename)
{
using(Stream destination = File.Create(filename))
Write(stream, destination);
}
//Typically I implement this Write method as a Stream extension method.
//The framework handles buffering.
public void Write(Stream from, Stream to)
{
for(int a = from.ReadByte(); a != -1; a = from.ReadByte())
to.WriteByte( (byte) a );
}
/*
Note, StreamReader is an IEnumerable<Char> while Stream is an IEnumbable<byte>.
The distinction is significant such as in multiple byte character encodings
like Unicode used in .Net where Char is one or more bytes (byte[n]). Also, the
resulting translation from IEnumerable<byte> to IEnumerable<Char> can loose bytes
or insert them (for example, "\n" vs. "\r\n") depending on the StreamReader instance
CurrentEncoding.
*/
public void CopyStream(Stream stream, string destPath)
{
using (var fileStream = new FileStream(destPath, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(fileStream);
}
}
stream
в скобку using(){}
. Ваш метод не создал поток, поэтому он не должен его утилизировать.
– LarsTech
1 August 2013 в 22:16
FileStream
вместо использования, иначе он будет оставаться открытым, пока не будет собран мусор.
– Pavel Chikulaev
17 January 2014 в 01:55
File.WriteAllBytes(destinationFilePath, input.ToArray());
. В моем случае input
является MemoryStream
, исходящим из ZipArchive
.
– SNag
10 January 2016 в 02:50
Вы не должны использовать StreamReader
для двоичных файлов (например, gif или jpg). StreamReader
для данных text . Вы почти , конечно, теряете данные, если используете их для произвольных двоичных данных. (Если вы используете Encoding.GetEncoding (28591), вы, вероятно, будете в порядке, но в чем смысл?)
Зачем вам вообще нужно использовать StreamReader
? Почему бы просто не сохранить двоичные данные в качестве двоичных данных и записать их на диск (или SQL) в виде двоичных данных?
EDIT: поскольку это, кажется, то, что люди хотят видеть ... если вы do просто хотите скопировать один поток в другой (например, в файл), используйте что-то вроде этого:
/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
Чтобы использовать его для сброса потока в файл, например:
using (Stream file = File.Create(filename))
{
CopyStream(input, file);
}
Обратите внимание, что Stream.CopyTo
был введен в .NET 4, служащий в основном той же цели.
Как было подчеркнуто Tilendor в ответе Джона Скита, потоки имеют метод CopyTo
с .NET 4.
var fileStream = File.Create("C:\\Path\\To\\File");
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin);
myOtherObject.InputStream.CopyTo(fileStream);
fileStream.Close();
Или с синтаксисом using
:
using (var fileStream = File.Create("C:\\Path\\To\\File"))
{
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin);
myOtherObject.InputStream.CopyTo(fileStream);
}
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
, если вы еще не в начале, или вы не будете копировать весь поток.
– Steve Rukuts
22 March 2012 в 14:00
fileStream
– Antoine Leclair
29 June 2016 в 17:05
public void testdownload(stream input)
{
byte[] buffer = new byte[16345];
using (FileStream fs = new FileStream(this.FullLocalFilePath,
FileMode.Create, FileAccess.Write, FileShare.None))
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, read);
}
}
}
FileStream
- приятно!
– vapcguy
12 October 2016 в 20:55
Другой вариант - передать поток в byte[]
и использовать File.WriteAllBytes
. Это должно сделать:
using (var stream = new MemoryStream())
{
input.CopyTo(stream);
File.WriteAllBytes(file, stream.ToArray());
}
Обертка его в методе расширения дает ему лучшее именование:
public void WriteTo(this Stream input, string file)
{
//your fav write method:
using (var stream = File.Create(file))
{
input.CopyTo(stream);
}
//or
using (var stream = new MemoryStream())
{
input.CopyTo(stream);
File.WriteAllBytes(file, stream.ToArray());
}
//whatever that fits.
}
File.WriteAllBytes(destinationFilePath, input.ToArray());
. В моем случае input
является MemoryStream
, исходящим из ZipArchive
.
– SNag
10 January 2016 в 02:50
stream.Seek(0, SeekOrigin.Begin);
– Nathan Bills
8 August 2016 в 22:06
Я не получаю все ответы, используя CopyTo
, где, возможно, системы, использующие приложение, возможно, не были обновлены до .NET 4.0+. Я знаю, что некоторые хотели бы заставить людей обновиться, но совместимость тоже хороша.
Другое дело, я не использую поток для копирования из другого потока в первую очередь. Почему бы просто не сделать:
byte[] bytes = myOtherObject.InputStream.ToArray();
Как только у вас есть байты, вы можете легко записать их в файл:
public static void WriteFile(string fileName, byte[] bytes)
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!path.EndsWith(@"\")) path += @"\";
if (File.Exists(Path.Combine(path, fileName)))
File.Delete(Path.Combine(path, fileName));
using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
{
fs.Write(bytes, 0, (int)bytes.Length);
fs.Close();
}
}
Этот код работает так, как я его тестировал файл .jpg
, хотя я признаю, что использовал его только с небольшими файлами (менее 1 МБ). Один поток, без копирования между потоками, без необходимости кодирования, просто напишите байты! Не нужно чрезмерно усложнять вещи с помощью StreamReader
, если у вас уже есть поток, который вы можете напрямую конвертировать в bytes
с помощью .ToArray()
!
Только потенциальные недостатки, которые я вижу при этом, - это если у вас есть большой файл, имеющий его как поток, а использование .CopyTo()
или эквивалента позволяет FileStream
передавать его, а не использовать байтовый массив и чтение байтов один за другим. В результате это может быть медленнее. Но он не должен задыхаться, так как метод .Write()
дескрипторов FileStream
записывает байты, и он выполняет только один байт за раз, поэтому он не будет забивать память, за исключением того, что вам нужно будет иметь достаточно памяти для хранения потока в качестве объекта byte[]
. В моей ситуации, когда я использовал это, получив OracleBlob
, я должен был перейти к byte[]
, он был достаточно маленьким, и, кроме того, для меня не было потоковой передачи, поэтому я просто отправил свои байты на мой функции [выше].
Другим вариантом, использующим поток, было бы использовать его с функцией CopyStream
Jon Skeet, которая была в другом сообщении, - это просто использует FileStream
для ввода входного потока и создания файл из него напрямую. Он не использует File.Create
, как и он (который изначально казался мне проблематичным, но позже обнаружил, что это скорее всего ошибка VS ...).
/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
public static void WriteFile(string fileName, Stream inputStream)
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!path.EndsWith(@"\")) path += @"\";
if (File.Exists(Path.Combine(path, fileName)))
File.Delete(Path.Combine(path, fileName));
using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
{
CopyStream(inputStream, fs);
}
inputStream.Close();
inputStream.Flush();
}
inputStream.Close()
, посмотрите еще раз - inputStream
отправляется как переменная. using
находится в выходном потоке path+filename
. Если вы говорили о fs.Close()
в середине using
, извините, вы были в этом уверены, и я удалил это.
– vapcguy
19 July 2017 в 15:52
byte[]
, я думаю, что было бы редко, если бы вы потоковали 1 GB + blob в файл ... если у вас нет сайта, на котором хранятся торренты на DVD. .. Кроме того, на большинстве компьютеров в настоящее время доступно не менее 2 ГБ ОЗУ. Во всяком случае ... Caveat действительно, но я думаю, что это случай, когда он, вероятно, «достаточно хорош», для большинства рабочих мест. – vapcguy 12 October 2016 в 20:50