2009-11-12 2 views
5

Supponiamo di avere un blocco di codice come questo:flusso Leggi Problema

//Assuming s is a stream: 
byte[] data = new byte[1000]; 
s.Read(data,0,data.Length); 

il metodo Read potrebbe leggere ovunque da 1 a 1000 byte, lasciando la equilibrio del torrente letto.

Questo è ciò che un libro C# dice.

Non capisco, perché il metodo Read dovrebbe leggere ovunque dal flusso? Non sta leggendo tutto il flusso?

E dice il work-around dovrebbe essere come questo:

//bytesRead will always end up at 1000, unless the stream is itself smaller in length: 
int bytesRead = 0; 
int chunkSize = 1; 
while(bytesRead < data.Length && chunkSize > 0) 
     bytesRead += chunkSize = s.Read(data,bytesRead,dataLength-bytesRead); 

Questo codice di cui sopra è fornito anche dal libro come un work-around. Quello che sto cercando di capire se il metodo Read sta iniziando a leggere fino alla fine e scrivere tutti i byte nell'intervallo specificato sull'array di byte. Perché sta usando il bytesRead come punto di partenza in s.Read(data,bytesRead,dataLength-bytesRead);

Grazie in anticipo.

risposta

8

L'idea è che i dati potrebbero non essere disponibili nel momento in cui si chiama Leggi ... o mai. Ad esempio, su un NetworkStream, i dati potrebbero arrivare più lentamente di quanto non lo stiate raccogliendo. Oppure potresti essere vicino alla fine di un FileStream. Lo Stream può sapere che ci sono meno byte rimanenti di quanto richiesto, o potrebbe non avere modo di sapere quando o se arriverà il colpo completo dei byte richiesti. Quindi, piuttosto che attendere i dati che potrebbero non arrivare mai, o fallire con un errore "non abbastanza, indovina di nuovo", Read si riserva il diritto di restituire meno di quanto richiesto.

Di conseguenza, durante la lettura di un blocco in un array di byte, è possibile che non si stia riempiendo l'array di byte. Ma vuoi che il prossimo pezzo venga aggiunto dove l'ultimo è stato interrotto, piuttosto che sovrascrivere l'inizio della matrice di byte. Quindi passare i byteLa base di partenza per posizionare il prossimo blocco nell'array di byte.

0

Sulla base della mia lettura della documentazione per il metodo di lettura, poiché i flussi possono essere utilizzati per leggere fonti di dati molto variabili, dall'input da tastiera ai file al traffico di rete, è stato lasciato aperto all'implementazione specifica se i dati sono stati restituiti da il metodo di lettura restituirà il numero richiesto di byte. Ad esempio, se un'implementazione particolare per la lettura dei dati di rete vuole restituire i 500 byte di dati che sono disponibili finora per una richiesta web, ma si aspetta che non venga eseguita finché non legge 1000 byte e hai richiesto 1000 byte, può restituire ciò che ha in modo da poterlo elaborare. Ti dirà che legge solo 500 byte e dovresti essere consapevole che potrebbero esserci altri in arrivo. Il valore massimo 1000 è solo un'indicazione che non si desidera elaborare più di 1000 byte alla volta.

2

Il primo esempio utilizza la dimensione dichiarata di 1000 dell'array di byte come parametro di input nel metodo Read.

Il secondo esempio sta leggendo il flusso un byte alla volta, il che è ottimo per lo streaming di dati in entrata o in uscita, ovvero se è possibile elaborare porzioni del flusso che si sta ricevendo senza prima averlo interamente memorizzato nella memoria, si tratta di un approccio più efficiente.

Penso che il punto in cui ci si confonde sia che l'autore limita artificialmente l'esempio a 1.000 byte al massimo.Molti protocolli che coinvolgono lo streaming in genere inviano un byte o due all'inizio specificando specificamente al consumatore la lunghezza del flusso nel suo complesso in modo tale da poter ridurre e elaborare il flusso in modo tale da non richiedere un limite dichiarato di 1.000. Ottieni la dimensione, la metti in modo appropriato (incluso l'ultimo chunk che potrebbe non essere la dimensione completa del chunk) e processa ogni chunk.

+0

Vuol dire che prima inviano la dimensione dei dati che vogliono inviare e poi inviano l'intero dato come parte di un blocco invece di inviarlo nel suo complesso? – Tarik

+0

Di solito sì. Supponiamo che tu abbia un file da 40 MB sul disco che vuoi trasferire. Anziché caricare 40 MB in memoria, quindi trasferirlo - e quindi rendere 40 MB di memoria affollati per un certo periodo di tempo - basta leggere, diciamo i primi 1024 byte, trasferirlo e continuare in blocchi da 1024 byte. Un protocollo di trasferimento file può dichiarare "i primi due byte del primo pacchetto contiene un int non firmato che indica la dimensione del payload" in modo da sapere quando interrompere la lettura da quel flusso. La parte ricevente può fare lo stesso, inserendola in 1024 byte o in un altro numero di buffer amichevole. – cfeduke

1

Non capisco, perché il metodo di lettura dovrebbe leggere ovunque dal flusso? Non sta leggendo tutto il flusso?

Leggi consente di specificare l'inizio e il punto finale per la lettura. Vedi la risposta di itowlson per maggiori informazioni.

Quello che sto cercando di capire se Leggi metodo sta cominciando a leggere ai alla fine e scrivere tutti i byte in campo specificato a matrice di byte.

Se questa era una domanda, suppongo che la risposta sia no. Il metodo Read riempie un array con i dati di uno stream nei punti iniziale e finale specificati.

Perché utilizza i byte come punto di partenza in s.Lead (dati, byteLeggi, dataLunghezza-byteLeggi);

Si sta utilizzando bytesRead per tenere traccia di "la quantità di byte letti". Questo gli consente di sapere da dove iniziare a leggere nella prossima chiamata Leggi.

4

La frase "potrebbe leggere ovunque da 1 a 1000 byte" significa "potrebbe leggere 1 byte o 2 byte, fino a 1000 byte". Si riferisce alla lunghezza di byte letti, non alla posizione. La lettura sarà situata nella posizione attuale del flusso.