Non ottengo tutte le risposte usando CopyTo
, dove forse i sistemi che utilizzano l'app potrebbero non essere stati aggiornati a .NET 4.0+. So che alcuni vorrebbero costringere le persone ad aggiornare, ma anche la compatibilità è buona.
Un'altra cosa, in primo luogo non riesco a utilizzare uno stream per copiare da un altro stream. Perché non fare solo:
byte[] bytes = myOtherObject.InputStream.ToArray();
Una volta che hai i byte, puoi facilmente scriverli in un file:
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();
}
}
Questo codice funziona come l'ho testato con un .jpg
file, anche se ammetto di averlo usato solo con file piccoli (meno di 1 MB). Un flusso, nessuna copia tra i flussi, nessuna codifica necessaria, basta scrivere i byte! Non c'è bisogno di complicare eccessivamente le cose StreamReader
se hai già un flusso con cui puoi convertirlo bytes
direttamente .ToArray()
!
Solo i potenziali svantaggi che posso vedere nel farlo in questo modo è se c'è un file di grandi dimensioni che hai, averlo come flusso e l'utilizzo .CopyTo()
o equivalente consente FileStream
di eseguire lo streaming invece di utilizzare un array di byte e leggere i byte uno per uno. Di conseguenza, potrebbe essere più lento farlo in questo modo. Ma non dovrebbe soffocare dal momento che il .Write()
metodo degli FileStream
handle scrive i byte e lo sta facendo solo un byte alla volta, quindi non ostruirà la memoria, tranne per il fatto che dovrai avere memoria sufficiente per contenere lo stream come byte[]
oggetto . Nella mia situazione in cui l'ho usato, ottenendo un OracleBlob
, dovevo andare a un byte[]
, era abbastanza piccolo e, inoltre, non c'era streaming disponibile per me, quindi ho appena inviato i miei byte alla mia funzione, sopra.
Un'altra opzione, usando un flusso, sarebbe quella di usarlo con la CopyStream
funzione di Jon Skeet che era in un altro post - questo usa solo FileStream
per prendere il flusso di input e creare il file direttamente da esso. Non usa File.Create
, come ha fatto lui (che inizialmente mi è sembrato problematico, ma in seguito ha scoperto che probabilmente era solo un bug 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();
}