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