Я не получаю ответы на все вопросы, используя 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
Джона Скита, которая была в другом посте - она просто использует 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();
}