Я не получаю все ответы, используя 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();
}