Я не отримую всіх відповідей за допомогою 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();
}