Nie otrzymuję wszystkich odpowiedzi CopyTo
, a być może systemy korzystające z aplikacji mogły nie zostać zaktualizowane do wersji .NET 4.0+. Wiem, że niektórzy chcieliby zmusić ludzi do aktualizacji, ale kompatybilność też jest dobra.
Inna sprawa, że nie używam strumienia do kopiowania z innego strumienia. Dlaczego nie tylko:
byte[] bytes = myOtherObject.InputStream.ToArray();
Gdy masz bajty, możesz łatwo zapisać je w pliku:
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();
}
}
Ten kod działa tak, jak przetestowałem go z .jpg
plikiem, choć przyznaję, że użyłem go tylko z małymi plikami (mniej niż 1 MB). Jeden strumień, bez kopiowania między strumieniami, niepotrzebne kodowanie, wystarczy napisać bajty! Nie musisz nadmiernie komplikować rzeczy, StreamReader
jeśli masz już strumień, na który można bytes
bezpośrednio przekonwertować.ToArray()
!
Jedyne potencjalne wady, które widzę podczas robienia tego w ten sposób, to to, że masz duży plik, mając go jako strumień, a użycie .CopyTo()
lub odpowiednik pozwala FileStream
na przesyłanie strumieniowe zamiast korzystania z tablicy bajtów i odczytywania bajtów jeden po drugim. W rezultacie może być wolniej. Ale nie powinien się dusić, ponieważ .Write()
metoda FileStream
uchwytów zapisujących bajty, i robi to tylko jeden bajt na raz, więc nie zapycha pamięci, z wyjątkiem tego, że będziesz musiał mieć wystarczającą ilość pamięci, aby utrzymać strumień jako byte[]
przedmiot . W mojej sytuacji, w której korzystałem z tego, OracleBlob
musiałem iść do byte[]
, był wystarczająco mały, a poza tym i tak nie było dla mnie żadnego streamingu, więc po prostu wysłałem moje bajty do mojej funkcji powyżej.
Inną opcją, wykorzystującą strumień, byłoby użycie go z CopyStream
funkcją Jona Skeeta, która była w innym poście - służy to tylko FileStream
do pobrania strumienia wejściowego i utworzenia z niego bezpośrednio pliku. Nie działa File.Create
, tak jak on (co początkowo wydawało mi się problematyczne, ale później stwierdził, że to prawdopodobnie tylko błąd 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();
}