C # utilizzando flussi


116

I flussi sono un po 'misteriosi per me. Non so quando usare quale stream e come usarli. Qualcuno può spiegarmi come vengono utilizzati i flussi?

Se ho capito bene, ci sono tre tipi di stream:

  • stream
  • read stream
  • write stream

È corretto? E, ad esempio, qual è la differenza tra a Memorystreame a FileStream?


13
si consiglia di controllare stackoverflow.com/questions/507747/...
Preets

3
Prendi un array di byte e quindi crea un wrapper per esso ( Stream) che espone alcuni metodi utili come leggere, scrivere e cambiare posizione. Ora puoi creare classi in base al loro archivio di backup (FileStream, MemoryStream) che ereditano Streame si basano su quella funzionalità in base al particolare archivio di backup.
The Muffin Man

Risposte:


80

Un flusso è un oggetto utilizzato per trasferire i dati. Esiste una classe di flusso generica System.IO.Stream, da cui derivano tutte le altre classi di flusso in .NET. La Streamclasse si occupa di byte.

Le classi concrete stream vengono utilizzate per trattare altri tipi di dati oltre ai byte. Per esempio:

  • La FileStreamclasse viene utilizzata quando la fonte esterna è un file
  • MemoryStream viene utilizzato per memorizzare i dati in memoria
  • System.Net.Sockets.NetworkStream gestisce i dati di rete

I flussi di lettura / scrittura come StreamReadere StreamWriternon sono flussi: non sono derivati ​​da System.IO.Stream, sono progettati per aiutare a scrivere e leggere dati da e per lo streaming!


3
Quindi, se ho capito bene, il flusso contiene i dati e non fa nulla con esso. Le classi "helper" del lettore e dello scrittore possono gestire (manipolare) i dati all'interno del flusso?
Martijn

9
No, Stream non è un contenitore di dati, lo utilizza per trasferire i dati, ad esempio FileStream trasferisce i dati da byte [] a file fisici, NetworkStream trasferisce byte [] per socket. Le classi Reader Writer sono classi di supporto per la scrittura e la lettura da stream, ad esempio StreamReader può essere utilizzato per leggere da Stream string non byte []. se fornisci FileStream come parametro leggerà da File, se NetworkStream dal socket.
Arsen Mkrtchyan

Inoltre, StreamReader e StreamWriter servono per leggere e scrivere flussi di TESTO (caratteri).
1c1cle

1
c'è un buon articolo per aiutarti a capire MemoryStream. codeproject.com/Articles/832387/…
Jiaji Li,

2
@ user420667. buona domanda. In entrambi i casi AudioStream e TemperatureStream, molto probabilmente sarebbero BinaryStream per il driver associato al dispositivo. In alternativa, puoi creare un CustomStream creato appositamente per l'interfaccia.
1c1cle

62

Per espandere un po 'altre risposte qui e aiutare a spiegare gran parte del codice di esempio che vedrai punteggiato, la maggior parte delle volte non leggi e scrivi direttamente in uno stream. I flussi sono un mezzo di basso livello per trasferire i dati.

Noterai che le funzioni di lettura e scrittura sono tutte orientate ai byte, ad esempio WriteByte (). Non ci sono funzioni per trattare numeri interi, stringhe, ecc. Questo rende il flusso molto generico, ma meno semplice da usare se, diciamo, vuoi solo trasferire del testo.

Tuttavia, .NET fornisce classi che convertono tra tipi nativi e l'interfaccia del flusso di basso livello e trasferisce i dati al o dal flusso per te. Alcune classi degne di nota sono:

StreamWriter // Badly named. Should be TextWriter.
StreamReader // Badly named. Should be TextReader.
BinaryWriter
BinaryReader

Per usarli, prima acquisisci il tuo stream, quindi crei una delle classi sopra e la associ allo stream. Per esempio

MemoryStream memoryStream = new MemoryStream();
StreamWriter myStreamWriter = new StreamWriter(memoryStream);

StreamReader e StreamWriter convertono tra i tipi nativi e le loro rappresentazioni di stringa, quindi trasferiscono le stringhe da e verso il flusso come byte. Così

myStreamWriter.Write(123);

scriverà "123" (tre caratteri "1", "2" e poi "3") nello stream. Se hai a che fare con file di testo (es. Html), StreamReader e StreamWriter sono le classi che useresti.

Mentre

myBinaryWriter.Write(123);

scriverà quattro byte che rappresentano il valore intero a 32 bit 123 (0x7B, 0x00, 0x00, 0x00). Se hai a che fare con file binari o protocolli di rete, BinaryReader e BinaryWriter sono ciò che potresti usare. (Se stai scambiando dati con reti o altri sistemi, devi essere consapevole dell'endianness , ma questo è un altro post.)


Le classi di adattatori StreamWriter e Reader hanno nomi seriamente male. Grazie per averlo detto. Come mai hanno inventato questo nome è ancora sorprendente per me.
Tarik

Inoltre, anche le classi binary writer e reader hanno un nome sbagliato.
Tarik

22

Gli stream sono utili per gestire grandi quantità di dati. Quando non è pratico caricare tutti i dati in memoria contemporaneamente, è possibile aprirlo come flusso e lavorare con piccoli pezzi di esso.


1
Mi piacerebbe vedere un esempio di ciò che hai appena detto "lavora con piccoli pezzi".
Jenna Leaf

2
Gli stream vanno bene anche per piccole quantità di dati. Se un programmatore C # vuole manipolare il contenuto di un file, deve usare i flussi, indipendentemente dalla quantità di dati. La stessa affermazione vale anche per i flussi di rete. Certo, se il programmatore sta codificando è un linguaggio di livello inferiore come C, allora è possibile scrivere caratteri o byte direttamente su un disco o un socket, ma anche per una piccola quantità di dati, richiede tempo e più incline a errore.
1c1cle

10

Il flusso è solo un'astrazione (o un wrapper) su un physicalflusso di byte. Questo physicalflusso è chiamato base stream. Quindi c'è sempre un flusso di base su cui viene creato un wrapper di flusso e quindi il wrapper prende il nome dal tipo di flusso di base, ad esempio FileStream, MemoryStreamecc.

Il vantaggio del wrapper di flusso è che ottieni un'API unificata per interagire con flussi di qualsiasi tipo sottostante usb, fileecc.

Perché dovresti trattare i dati come flusso : poiché i blocchi di dati vengono caricati su richiesta, possiamo ispezionare / elaborare i dati come blocchi anziché caricare tutti i dati in memoria. Questo è il modo in cui la maggior parte dei programmi gestisce file di grandi dimensioni, ad esempio crittografare un file immagine del sistema operativo.


4

C'è solo un tipo base di Stream. Tuttavia, in varie circostanze, alcuni membri genereranno un'eccezione quando chiamati perché in quel contesto l'operazione non era disponibile.

Ad esempio a MemoryStreamè semplicemente un modo per spostare i byte dentro e fuori un pezzo di memoria. Quindi puoi chiamare Lettura e scrittura su di esso.

D'altra parte a FileStreamti permette di leggere o scrivere (o entrambi) da / a un file. Se puoi effettivamente leggere o scrivere dipende da come è stato aperto il file. Non è possibile scrivere su un file se è stato aperto solo per l'accesso in lettura.


3

Comincerei leggendo sugli stream su MSDN: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

Memorystream e FileStream sono flussi utilizzati per lavorare rispettivamente con la memoria grezza e i file ...


Grazie per il collegamento. Mi è piaciuto il fatto che "è possibile sfogliare il codice sorgente online, scaricare il riferimento per la visualizzazione offline e scorrere le fonti (comprese le patch e gli aggiornamenti) durante il debug". Questa funzione offre un nuovo livello di conoscenza.
David

1

Non chiamerei quei diversi tipi di flussi. La classe Stream ha proprietà CanRead e CanWrite che indicano se il flusso specifico può essere letto e scritto.

La principale differenza tra le diverse classi di stream (come MemoryStream vs FileStream) è l'archivio di backup, da dove vengono letti i dati o in cui vengono scritti. È abbastanza ovvio dal nome. Un MemoryStream archivia i dati solo in memoria, un FileStream è supportato da un file su disco, un NetworkStream legge i dati dalla rete e così via.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.