Come posso & # 8220; fork & # 8221; uno streaming in .NET?
-
06-07-2019 - |
Domanda
Come discusso prima , quando un BinaryReader o BinaryWriter viene chiuso, anche il suo Stream sottostante viene chiuso (aargh). Considera questa situazione: a un R
di routine viene passato un MemoryStream, ad esempio M
; Vorrei scrivere alcune cose su M
e poi passarle a un'altra routine per ulteriori elaborazioni (non necessariamente scrivendo). Per comodità, vorrei avvolgere M
in un BinaryWriter per scrivere. Dopo aver scritto, ho finito con BinaryWriter ma non con M
.
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 riesco a smaltire BinaryStream senza chiudere M
.
D: Esiste un modo per eseguire una delle seguenti operazioni?
- estrae il byte sottostante [] da un MemoryStream,
- clonare uno Stream
- riapri uno Stream dopo che è stato chiuso
Soluzione 4
Grazie a diversi che hanno suggerito ToArray, sono stato portato alla risposta giusta, che è "M.GetBuffer". ToArray non è poi così male, ma
- crea una copia
- ottiene solo una parte del buffer
GetBuffer prende semplicemente un riferimento al byte sottostante [], che è quello che sto cercando.
Altri suggerimenti
Dovresti ottenere meglio il buffer byte [] sottostante usando
byte[] buffer = ms.GetBuffer();
E quindi copiare i dati byte usando il metodo Array.Copy (). Sei libero di creare un nuovo stream con esso.
Puoi usare cose come MiscUtil.IO.NonClosingStreamWrapper
in MiscUtil , che racchiude un Stream
e ignora semplicemente le richieste Close
/ Dispose
. Proprio 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
}
Puoi:
- Chiama M.ToArray () per ottenere lo stream come una matrice di byte.
- Sottoclasse BinaryWriter e sovrascrive il metodo Dispose per impedire la chiusura del flusso figlio
Solo per aggiungerlo qui, una soluzione molto semplice sarebbe non eliminare Dispose () 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 devi solo preoccuparti 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 smaltirsi.
Un approccio un po 'ingenuo è usare
byte buf[] = MemoryStream.ToArray();
Per copiare il contenuto del flusso in un array di byte. Puoi trasformarlo in uno stream con
MemoryStream ms = new MemoryStream(buf);
Accedere a this M.Clone (); dovrebbe funzionare. Ma potrei sbagliarmi ...