2009-10-27 13 views
8

Come discussed before, quando un BinaryReader o BinaryWriter viene chiuso, anche il suo Stream sottostante viene chiuso (aargh). Prendi in considerazione questa situazione: una routine R riceve un MemoryStream, ad esempio M; Vorrei scrivere alcune cose su M e poi passarlo a un'altra routine per ulteriori elaborazioni (non necessariamente scrivere). Per comodità, mi piacerebbe avvolgere M in un BinaryWriter per scrivere. Dopo aver scritto, ho finito con il BinaryWriter ma non con M.Come si "forchetta" un flusso in .NET?

void R(MemoryStream M) 
{ 
    using (B = new BinaryWriter(M)) 
    { 
     // write some stuff using B 
    } 

    S(M); // now pass M to another routine for further processing 
} 

Ma, non posso smaltire la BinaryStream senza chiudere M.

D: Esiste un modo per eseguire una delle seguenti azioni?

  • estrarre il byte sottostante [] da un MemoryStream,
  • clone un flusso
  • riapre un flusso dopo che è stato chiuso
+0

Non conosco C#, ma in Java, basta semplicemente abbandonare senza chiudere BinaryWriter. L'uso della forza costruttiva {}} non si chiude? Quindi non usare quel costrutto! –

+0

P.S. Ma devi assicurarti di scaricare BinaryWriter prima di abbandonarlo. –

risposta

2

Grazie a diversi utenti che hanno suggerito ToArray, sono stato indirizzato alla risposta corretta, che è "M.GetBuffer". ToArray non è male, ma

  • fa una copia
  • ottiene solo una parte del buffer

GetBuffer afferra solo un riferimento al byte sottostante [], che è quello che sto dopo.

+0

che è stato indicato nella mia risposta ;) –

0

Un po approccio naive consiste nell'utilizzare

byte buf[] = MemoryStream.ToArray(); 

Per copiare il contenuto del flusso in un array di byte. È possibile attivare nuovamente in un flusso con

MemoryStream ms = new MemoryStream(buf); 
+0

Vale la pena sottolineare: questo metodo funziona su uno stream chiuso e uno live. –

2

È possibile:

  • chiamata M.ToArray() per ottenere il flusso come un array di byte.
  • sottoclasse BinaryWriter e sovrascrivere il metodo Dispose per impedire la chiusura del flusso di bambino
+0

+1 in modo specifico per l'override di Dispose. –

+0

Non puoi semplicemente evitare di chiamare close/Dispose? –

-1

accoring al this M.Clone(); dovrebbe funzionare. Ma potrei sbagliarmi ...

+0

-1 per la pubblicazione su un sito Web che non consente la visualizzazione dei contenuti gratuitamente, che è praticamente inutile –

7

Si dovrebbe meglio ottenere il buffer di byte sottostante [] utilizzando

byte[] buffer = ms.GetBuffer(); 

E poi copiare i dati di byte utilizzando il metodo Array.Copy(). Sei libero di creare un nuovo flusso con esso.

+0

Non capisco perché stai dicendo che è meglio usare GetBuffer e quindi fare una copia usando Array.Copy. Se volessi una copia, userei semplicemente ToArray. –

+0

Da MSDN doc Questo metodo omette i byte inutilizzati in MemoryStream dall'array. Per ottenere l'intero buffer, utilizzare il metodo GetBuffer. http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx –

+0

Il precedente "questo metodo" si riferisce al MemoryStream.ToArray() –

5

È possibile utilizzare le cose come il MiscUtil.IO.NonClosingStreamWrapper in MiscUtil, che avvolge un Stream e semplicemente ignora Close/Dispose richieste. Solo per questo scopo.

void R(MemoryStream M) 
{ 
    using (B = new BinaryWriter(new NonClosingStreamWrapper(M))) 
    { 
     // write some stuff using B 
    } 

    S(M); // now pass M to another routine for further processing 
}  
1

solo aggiungere che qui, una soluzione molto semplice sarebbe non di smaltire() lo scrittore.

void R(MemoryStream M) 
{ 
    B = new BinaryWriter(M); 

    // write some stuff using B   
    B.Flush(); 
    S(M); // now pass M to another routine for further processing 
} 

Ora ci si deve solo preoccupare di mantenere B nell'ambito, che sarà durante R().

Questa potrebbe non essere la soluzione migliore qui, ma vale la pena notare che i Lettori e gli Scrittori non hanno bisogno di Smaltimento.

+0

Speriamo che 'BinaryWriter' non bufferizzi nulla, quindi ... –

+0

Ma assicurati di chiamare B.flush() dopo averlo terminato nel caso in cui non abbia passato tutto a M. (That's cosa sarebbe necessario in Java, nessuna idea di C#) –

+0

OK, Adrian e Marc, ho dimenticato di Flush(). –