Puoi spiegare il concetto di flussi?

Capisco che uno stream è una rappresentazione di una sequenza di byte. Ogni stream fornisce i mezzi per leggere e scrivere byte nel proprio backing store. Ma qual è il punto del stream? Perché il backing store non è ciò con cui interagiamo?

Per qualche ragione questo concetto non mi sta facendo clic. Ho letto un sacco di articoli, ma penso di aver bisogno di un’analogia o qualcosa del genere.

La parola “stream” è stata scelta perché rappresenta (nella vita reale) un significato molto simile a ciò che vogliamo trasmettere quando lo usiamo.

Dimentichiamo un po ‘il backing store e iniziamo a pensare all’analogia con un stream d’acqua. Riceverai un stream continuo di dati, proprio come l’acqua scorre continuamente in un fiume. Non si sa necessariamente da dove provengono i dati, e molto spesso non è necessario; sia da un file, da un socket o da qualsiasi altra fonte, non ha importanza (non dovrebbe). Questo è molto simile a ricevere un stream d’acqua, per cui non è necessario sapere da dove proviene; sia da un lago, da una fontana o da qualsiasi altra fonte, non importa (non dovrebbe) importa davvero.

Detto questo, una volta che inizi a pensare che ti interessa solo ottenere i dati di cui hai bisogno, indipendentemente da dove provenga, le astrazioni di cui le altre persone hanno parlato diventano più chiare. Inizi a pensare che puoi avvolgere i flussi e i tuoi metodi funzioneranno perfettamente. Ad esempio, potresti fare questo:

int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); } // in another method: Stream fileStream = new FileStream("My Data.dat"); Stream zipStream = new ZipDecompressorStream(fileStream); Stream decryptedStream = new DecryptionStream(zipStream); StreamReader reader = new StreamReader(decryptedStream); int x = ReadInt(reader); 

Come vedi, diventa molto facile cambiare la tua fonte di input senza modificare la logica di elaborazione. Ad esempio, per leggere i dati da un socket di rete anziché da un file:

 Stream stream = new NetworkStream(mySocket); StreamReader reader = new StreamReader(stream); int x = ReadInt(reader); 

Facile come può essere. E la bellezza continua, dato che puoi usare qualsiasi tipo di sorgente di input, purché tu possa creare un “wrapper” di streaming per esso. Potresti anche fare questo:

 public class RandomNumbersStreamReader : StreamReader { private Random random = new Random(); public String ReadLine() { return random.Next().ToString(); } } // and to call it: int x = ReadInt(new RandomNumbersStreamReader()); 

Vedere? Finché il tuo metodo non si cura di quale sia la fonte di input, puoi personalizzare la tua fonte in vari modi. L’astrazione ti consente di disaccoppiare l’input dalla logica di elaborazione in un modo molto elegante.

Si noti che il stream che abbiamo creato noi stessi non ha un backing store, ma serve ancora perfettamente ai nostri scopi.

Quindi, per riassumere, un stream è solo una fonte di input, nascondendo (estraendo) un’altra fonte. Finché non interromperai l’astrazione, il tuo codice sarà molto flessibile.

Il punto è che non dovresti sapere cosa sia il backing store – è un’astrazione su di esso. In effetti, potrebbe non esserci nemmeno un backing store: si potrebbe leggere da una rete e i dati non verranno mai “memorizzati”.

Se riesci a scrivere codice che funzioni sia che tu stia parlando con un file system, memoria, una rete o qualsiasi altra cosa che supporti l’idea del stream, il tuo codice è molto più flessibile.

Inoltre, i flussi sono spesso concatenati – puoi avere un stream che comprime tutto ciò che viene inserito, scrivendo il modulo compresso su un altro stream o uno che crittografa i dati, ecc. All’altro capo ci sarebbe il contrario catena, decifrare, decomprimere o qualsiasi altra cosa.

Il punto del stream è quello di fornire uno strato di astrazione tra te e il backing store. Quindi un dato blocco di codice che usa un stream non deve preoccuparsi se il backing store è un file su disco, memoria, ecc …

Non si tratta di flussi: si tratta di nuotare. Se riesci a nuotare in un stream, puoi nuotare in qualsiasi stream che incontri.

Per aggiungere alla camera dell’eco, il stream è un’astrazione, quindi non ti interessa il negozio sottostante. Ha più senso quando si considerano gli scenari con e senza flussi.

I file non sono interessanti per la maggior parte perché gli stream non fanno molto al di sopra e al di là dei metodi non basati sul stream che mi sono familiari. Iniziamo con i file di Internet.

Se voglio scaricare un file da internet, devo aprire un socket TCP, fare una connessione e ricevere byte finché non ci sono più byte. Devo gestire un buffer, conoscere le dimensioni del file previsto e scrivere codice per rilevare quando la connessione viene interrotta e gestirla in modo appropriato.

Diciamo che ho una sorta di object TcpDataStream. Lo creo con le informazioni di connessione appropriate, quindi leggo i byte dallo stream finché non dice che non ci sono altri byte. Lo stream gestisce la gestione del buffer, le condizioni di fine dei dati e la gestione delle connessioni.

In questo modo, i flussi semplificano l’I / O. Potresti sicuramente scrivere una class TcpFileDownloader che fa ciò che fa il stream, ma poi hai una class specifica per TCP. La maggior parte delle interfacce di streaming fornisce semplicemente un metodo Read () e Write (), mentre i concetti più complessi sono gestiti dall’implementazione interna. Per questo motivo, è ansible utilizzare lo stesso codice di base per leggere o scrivere su memoria, file su disco, socket e molti altri archivi dati.

È solo un concetto, un altro livello di astrazione che ti semplifica la vita. E hanno tutti un’interfaccia comune che significa che puoi combinarli in un modo simile alla pipa. Ad esempio, codifica su base64, quindi fai zip e quindi scrivi su disco e tutto in una riga!

La visualizzazione che uso sono i nastri trasportatori, non nelle fabbriche reali perché non ne so nulla, ma nelle fabbriche di cartoni animati in cui gli oggetti si muovono lungo le linee e vengono timbrati e incassati e contati e controllati da una sequenza di dispositivi stupidi.

Hai componenti semplici che fanno una cosa, ad esempio un dispositivo per mettere una ciliegina sulla torta. Questo dispositivo ha un stream di input di torte senza ciliegia e un stream in uscita di torte con ciliegie. Ci sono tre vantaggi che vale la pena ricordare strutturando il tuo processo in questo modo.

In primo luogo semplifica i componenti stessi: se vuoi mettere la glassa di cioccolato su una torta, non hai bisogno di un dispositivo complicato che sappia tutto sulle torte, puoi creare un dispositivo stupido che appiccica la glassa al cioccolato su qualsiasi cosa ci venga immessa (in le vignette, questo arriva a non sapere che il prossimo object non è una torta, è Wile E. Coyote).

In secondo luogo puoi creare diversi prodotti mettendo i dispositivi in ​​sequenze diverse: forse vuoi che i tuoi dolci abbiano la ciliegina sulla ciliegina anziché la ciliegina sulla cima della glassa, e puoi farlo semplicemente scambiando i dispositivi in ​​giro sulla linea .

In terzo luogo, i dispositivi non hanno bisogno di gestire l’inventario, il pugilato o l’unboxing. Il modo più efficiente di aggregare e confezionare le cose è mutevole: forse oggi metti i tuoi dolci in scatole da 48 e li mandi fuori dal camion, ma domani vuoi spedire scatole da sei in risposta a ordini personalizzati. Questo tipo di cambiamento può essere risolto sostituendo o riconfigurando le macchine all’inizio e alla fine della linea di produzione; la macchina di ciliegie nel mezzo della linea non deve essere modificata per elaborare un numero diverso di elementi alla volta, funziona sempre con un articolo alla volta e non deve sapere in che modo il suo input o output è essere raggruppati.

La migliore spiegazione dei flussi che ho visto è il capitolo 3 di SICP . (Potrebbe essere necessario leggere i primi 2 capitoli perché abbia senso, ma dovresti comunque. 🙂

Non usano affatto sterams per byte, ma piuttosto interi. I grandi punti che ho ottenuto da esso erano:

  • Gli stream sono elenchi ritardati
  • Il sovraccarico computazionale [di calcolare avidamente tutto in anticipo, in alcuni casi] è oltraggioso
  • Possiamo usare gli stream per rappresentare sequenze che sono infinitamente lunghe

In Computer Science, un stream è un stream continuo di informazioni.

Quando penso allo streaming, penso a un servizio di consegna di dati video. Anche se lo streaming non è limitato al video. Anche i file di testo, audio e zip possono essere in streaming. Inoltre, lo streaming non è limitato ai file. Anche le connessioni HTTP, FTP, SSH e Input / Output possono essere trasmesse in streaming.

Per comprendere il concetto di streaming è ansible confrontare altri concetti di distribuzione dei dati.

Il download di file classici non avviene in tempo reale. Prima di utilizzare il file, dovrai attendere fino al completamento del download.

Il download progressivo consente di guardare il file video mentre viene scaricato. L’avanzamento e riavvolgimento veloce è ansible. Per fare ciò utilizza un buffer che memorizza i dati temporanei nella memoria del computer che riceve il file video. Anche se i dati sono frammentati, non è lo streaming reale.

Lo streaming avviene in tempo reale e dati di chunk. Lo streaming è implementato nelle trasmissioni in diretta. I client che ascoltano la trasmissione non possono eseguire l’avanzamento rapido o il riavvolgimento. Negli stream video, i dati vengono scartati dopo la riproduzione.

Un server di streaming mantiene una connessione a 2 vie con il proprio client, mentre un server Web chiude la connessione dopo una risposta del server.

Link utili:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011 Fornisce una presentazione molto chiara
  2. https://www.sk89q.com/2010/04/introduction-to-php-streams/
  3. http://www.netlingo.com/word/stream-or-streaming.php
  4. http://www.brainbell.com/tutorials/php/Using_PHP_Streams.htm
  5. http://www.sitepoint.com/php-streaming-output-buffering-explained/
  6. http://php.net/manual/en/wrappers.php
  7. http://www.digidata-lb.com/streaming/Streaming_Proposal.pdf
  8. http://www.webopedia.com/TERM/S/streaming.html
  9. http://php.net/manual/en/intro.stream.php
  10. https://en.wikipedia.org/wiki/Stream_%28computing%29

Un altro punto (per la lettura della situazione del file):

  1. stream ti consente di fare qualcos’altro prima di aver finished reading all content of the file .
  2. puoi risparmiare memoria, perché non è necessario caricare tutto il contenuto del file in una sola volta.

Pensa ai flussi come a una fonte astratta di dati (byte, caratteri, ecc.). Essi astraggono la meccanica attuale di lettura e scrittura sull’origine dati concreta, sia essa un socket di rete, un file su un disco o una risposta dal server web.

Penso che sia necessario considerare che lo stesso backing store è spesso solo un’altra astrazione. Un stream di memoria è abbastanza facile da capire, ma un file è radicalmente diverso a seconda del file system che stai usando, non importa quale disco rigido stai usando. Di fatto, non tutti gli stream si trovano in cima a un backing store: i flussi di rete sono semplicemente stream.

Il punto di un stream è che limitiamo la nostra attenzione a ciò che è importante. Avendo un’astrazione standard, possiamo eseguire operazioni comuni. Anche se non vuoi, ad esempio, cercare un file o una risposta HTTP per gli URL oggi, non significa che non desideri domani.

Gli stream erano originariamente concepiti quando la memoria era minuscola rispetto allo stoccaggio. Basta leggere un file C potrebbe essere un carico significativo. Ridurre al minimo l’impronta della memoria era estremamente importante. Quindi, un’astrazione in cui pochissimo doveva essere caricato era molto utile. Oggi è ugualmente utile quando si eseguono le comunicazioni di rete e, raramente, ciò risulta restrittivo quando gestiamo i file. La possibilità di aggiungere in modo trasparente cose come il buffering in un modo generale lo rende ancora più utile.

Un stream è un riassunto di una sequenza di byte. L’idea è che non hai bisogno di sapere da dove vengono i byte, solo che puoi leggerli in maniera standardizzata.

Ad esempio, se si elaborano i dati tramite uno stream, non importa il codice se i dati provengono da un file, una connessione di rete, una stringa, un blob in un database ecc ecc. Ecc.

Non c’è nulla di sbagliato di per sé nell’interagire con il backing store stesso, tranne per il fatto che ti lega all’implementazione del backing store.

Un stream è un’astrazione che fornisce un insieme standard di metodi e proprietà per l’interazione con i dati. Estrapolando dal supporto di archiviazione effettivo, è ansible scrivere il codice senza fare affidamento totale su quale sia il mezzo o addirittura sull’implementazione di quel supporto.

Una buona analogia potrebbe essere quella di considerare una borsa. Non ti importa di cosa è fatta una borsa o cosa fa quando ci metti le tue cose, a patto che la borsa svolga il compito di essere una borsa e tu possa far uscire le tue cose. Un stream definisce per i supporti di memorizzazione ciò che il concetto di borsa definisce per le diverse istanze di una borsa (come il sacco della spazzatura, la borsa, lo zaino, ecc.) – le regole dell’interazione.

Lo terrò breve, mi mancava solo la parola qui:

Gli stream sono code solitamente memorizzate nel buffer contenente qualsiasi tipo di dati.

(Ora, poiché tutti sappiamo quali sono le code, non c’è bisogno di spiegarlo ulteriormente.)