¿Puedes explicar el concepto de streams?

Entiendo que una secuencia es una representación de una secuencia de bytes. Cada secuencia proporciona medios para leer y escribir bytes en su tienda de respaldo determinada. Pero, ¿cuál es el sentido de la stream? ¿Por qué no es la tienda de respaldo en sí misma con la que interactuamos?

Por alguna razón, este concepto simplemente no está haciendo clic para mí. He leído muchos artículos, pero creo que necesito una analogía o algo así.

La palabra “secuencia” ha sido elegida porque representa (en la vida real) un significado muy similar a lo que queremos transmitir cuando lo usamos.

Olvidémonos un poco de la tienda de respaldo y comencemos a pensar en la analogía de una stream de agua. Usted recibe un flujo continuo de datos, al igual que el agua fluye continuamente en un río. No necesariamente sabe de dónde provienen los datos, y la mayoría de las veces no es necesario; ya sea desde un archivo, un socket o cualquier otra fuente, no importa (no debería). Esto es muy similar a recibir una stream de agua, por lo que no necesita saber de dónde viene; ya sea de un lago, una fuente o cualquier otra fuente, no importa (no debería).

Dicho esto, una vez que comienzas a pensar que solo te importa obtener la información que necesitas, independientemente de dónde provenga, las abstracciones de las que hablaron otras personas se vuelven más claras. Empiezas a pensar que puedes envolver flujos y tus métodos funcionarán perfectamente. Por ejemplo, podrías hacer esto:

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); 

Como puede ver, es muy fácil cambiar su fuente de entrada sin cambiar su lógica de procesamiento. Por ejemplo, para leer sus datos desde un socket de red en lugar de un archivo:

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

Tan fácil como puede ser. Y la belleza continúa, ya que puedes utilizar cualquier tipo de fuente de entrada, siempre y cuando puedas crear un “envoltorio” de transmisión para ella. Incluso podrías hacer esto:

 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()); 

¿Ver? Siempre que a su método no le importe cuál es la fuente de entrada, puede personalizar su fuente de varias maneras. La abstracción le permite desacoplar la entrada de la lógica de procesamiento de una manera muy elegante.

Tenga en cuenta que la transmisión que creamos nosotros mismos no tiene una tienda de respaldo, pero aún sirve para nuestros propósitos a la perfección.

Entonces, para resumir, una secuencia es solo una fuente de entrada, ocultando (abstrayendo) otra fuente. Mientras no rompas la abstracción, tu código será muy flexible.

El punto es que no debería tener que saber qué es la tienda de respaldo, es una abstracción sobre ella. De hecho, es posible que ni siquiera haya una tienda de respaldo; podría estar leyendo desde una red, y los datos nunca se “almacenan” en absoluto.

Si puede escribir código que funcione ya sea que esté hablando con un sistema de archivos, memoria, red o cualquier otra cosa que admita la idea de transmisión, su código es mucho más flexible.

Además, las transmisiones a menudo se encadenan juntas: puede tener una secuencia que comprima lo que se pone en ella, escribiendo la forma comprimida en otra secuencia, o una que encripte los datos, etc. En el otro extremo estaría el reverso cadena, descifrado, descompresión o lo que sea.

El objective de la transmisión es proporcionar una capa de abstracción entre usted y la tienda de respaldo. Por lo tanto, un bloque de código dado que utiliza un flujo no necesita preocuparse si el almacén de respaldo es un archivo de disco, memoria, etc.

No se trata de streams: se trata de nadar. Si puedes nadar un arroyo, entonces puedes nadar cualquier arroyo que encuentres.

Para agregar a la cámara de eco, la transmisión es una abstracción, por lo que no te importa la tienda subyacente. Tiene más sentido cuando se consideran escenarios con y sin flujos.

Los archivos son poco interesantes en su mayor parte porque las transmisiones no hacen mucho más allá de lo que hicieron los métodos no basados ​​en secuencias con los que estoy familiarizado. Comencemos con los archivos de internet.

Si quiero descargar un archivo de Internet, tengo que abrir un socket TCP, hacer una conexión y recibir bytes hasta que no haya más bytes. Tengo que administrar un búfer, conocer el tamaño del archivo esperado y escribir código para detectar cuándo se interrumpe la conexión y manejar esto de manera adecuada.

Digamos que tengo algún tipo de objeto TcpDataStream. Lo creo con la información de conexión adecuada, luego leo bytes de la transmisión hasta que dice que no hay más bytes. La secuencia maneja la gestión de búfer, las condiciones de fin de datos y la gestión de conexión.

De esta forma, las transmisiones hacen que las E / S sean más fáciles. Ciertamente podría escribir una clase TcpFileDownloader que hace lo que hace la secuencia, pero luego tiene una clase que es específica de TCP. La mayoría de las interfaces de flujo simplemente proporcionan un método Read () y Write (), y la implementación interna maneja cualquier concepto más complicado. Debido a esto, puede usar el mismo código básico para leer o escribir en la memoria, archivos de disco, sockets y muchos otros almacenes de datos.

Es solo un concepto, otro nivel de abstracción que te hace la vida más fácil. Y todos ellos tienen una interfaz común, lo que significa que puedes combinarlos de forma similar a una tubería. Por ejemplo, codifique a base64, luego comprima y luego escriba esto en el disco y todo en una sola línea.

La visualización que utilizo son cintas transportadoras, no en fábricas reales porque no sé nada de eso, pero en fábricas de caricaturas donde los artículos se mueven a lo largo de las líneas y son sellados y enmarcados, contados y controlados por una secuencia de dispositivos tontos.

Tiene componentes simples que hacen una cosa, por ejemplo, un dispositivo para poner un guinda a un pastel. Este dispositivo tiene un flujo de entrada de tortas sin cerezas y una secuencia de salida de tortas con cerezas. Hay tres ventajas que vale la pena mencionar para estructurar su procesamiento de esta manera.

En primer lugar, simplifica los componentes: si quieres poner chocolate en un pastel, no necesitas un dispositivo complicado que sepa todo sobre los pasteles, puedes crear un dispositivo tonto que pegue el glaseado de chocolate en cualquier cosa que se alimente en él (en las caricaturas, esto llega incluso a no saber que el siguiente artículo no es una torta, es Wile E. Coyote).

En segundo lugar, puedes crear diferentes productos colocando los dispositivos en diferentes secuencias: tal vez quieras que tus pasteles tengan glaseado encima del cerezo en lugar de cereza en la parte superior del glaseado, y puedes hacerlo simplemente intercambiando los dispositivos en la línea .

En tercer lugar, los dispositivos no necesitan administrar inventario, boxeo o unboxing. La forma más eficiente de agregar y empaquetar cosas es cambiante: quizás hoy coloque sus pasteles en cajas de 48 y las envíe en camiones, pero mañana querrá enviar cajas de seis en respuesta a pedidos personalizados. Este tipo de cambio puede adaptarse reemplazando o reconfigurando las máquinas al principio y al final de la línea de producción; la máquina de cerezas en el medio de la línea no tiene que cambiarse para procesar un número diferente de elementos a la vez, siempre funciona con un elemento a la vez y no tiene que saber cómo se genera su entrada o salida. siendo agrupado

La mejor explicación de las transmisiones que he visto es el capítulo 3 del SICP . (Puede que necesites leer los primeros 2 capítulos para que tenga sentido, pero deberías hacerlo de todos modos 🙂

No usan esterams para bytes, sino enteros. Los grandes puntos que obtuve de esto fueron:

  • Las transmisiones son listas retrasadas
  • La sobrecarga computacional [de calcular ansiosamente todo con anticipación, en algunos casos] es escandalosa
  • Podemos usar secuencias para representar secuencias que son infinitamente largas

En Informática, una stream es un flujo continuo de información.

Cuando pienso en la transmisión, pienso en un servicio de entrega de datos de video. Aunque la transmisión no está limitada a video. También se pueden transmitir archivos de texto, audio y zip. Además de eso, la transmisión no está limitada a los archivos. También se pueden transmitir las conexiones HTTP, FTP, SSH y Entrada / Salida.

Para comprender el concepto de transmisión, puede comparar otros conceptos de distribución de datos.

La descarga clásica de archivos no ocurre en tiempo real. Antes de tomar el archivo para usar, tendrá que esperar hasta que se complete la descarga.

La descarga progresiva permite ver el archivo de video a medida que se descarga. Avance rápido y rebobinado es posible. Para hacerlo, usa un buffer que almacena datos temporales en la memoria de la computadora que recibe el archivo de video. Aunque los datos están fragmentados, no se trata de transmisión real.

Streaming ocurre en tiempo real y fragmenta datos. Streaming se implementa en transmisiones en vivo. Los clientes que escuchan la transmisión no pueden avanzar o rebobinar rápidamente. En las transmisiones de video, los datos se descartan después de la reproducción.

Un Streaming Server mantiene una conexión bidireccional con su cliente, mientras que un servidor web cierra la conexión después de una respuesta del servidor.

Enlaces útiles:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011 Proporciona una presentación muy clara
  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

Otro punto (para leer la situación del archivo):

  1. stream puede permitirle hacer algo más antes de finished reading all content of the file .
  2. puede guardar memoria, porque no necesita cargar todo el contenido del archivo a la vez.

Piense en las streams como fuente abstracta de datos (bytes, caracteres, etc.). Resumen la mecánica actual de leer y escribir en la fuente de datos concreta, ya sea un socket de red, un archivo en un disco o una respuesta del servidor web.

Creo que debes tener en cuenta que la tienda de respaldo en sí es a menudo otra abstracción. Una secuencia de memoria es bastante fácil de entender, pero un archivo es radicalmente diferente según el sistema de archivos que esté usando, sin importar qué disco duro esté usando. No todas las transmisiones se ubican de hecho en la parte superior de una tienda de respaldo: las transmisiones de red simplemente son transmisiones.

El objective de una transmisión es que restrinjamos nuestra atención a lo que es importante. Al tener una abstracción estándar, podemos realizar operaciones comunes. Incluso si no desea, por ejemplo, buscar un archivo o una respuesta HTTP para las URL hoy, no significa que no desea hacerlo mañana.

Los flujos se concibieron originalmente cuando la memoria era pequeña en comparación con el almacenamiento. Solo leer un archivo C podría ser una carga significativa. Minimizar la huella de memoria fue extremadamente importante. Por lo tanto, una abstracción en la que muy poco necesitaba ser cargado era muy útil. Hoy en día, es igualmente útil cuando se realiza una comunicación de red y, en general, rara vez es restrictivo cuando se trata de archivos. La capacidad de agregar elementos de forma transparente como el almacenamiento en búfer de forma general lo hace aún más útil.

Una secuencia es una abstracción de una secuencia de bytes. La idea es que no necesita saber de dónde vienen los bytes, solo que puede leerlos de manera estandarizada.

Por ejemplo, si procesa datos a través de una transmisión, no le importa a su código si los datos provienen de un archivo, una conexión de red, una cadena, un blob en una base de datos, etc. etc., etc.

No hay nada de malo en sí mismo al interactuar con la propia tienda de respaldo, excepto por el hecho de que lo vincula con la implementación de la tienda de respaldo.

Una secuencia es una abstracción que proporciona un conjunto estándar de métodos y propiedades para interactuar con datos. Al abstraerse del medio de almacenamiento real, su código puede escribirse sin depender totalmente de qué es ese medio o incluso la implementación de ese medio.

Una buena analogía podría ser considerar una bolsa. No le importa de qué está hecha una bolsa ni qué hace cuando coloca sus cosas en ella, siempre que la bolsa haga el trabajo de ser una bolsa y pueda recuperar sus cosas. Una secuencia define para medios de almacenamiento lo que el concepto de bolsa define para diferentes instancias de una bolsa (como bolsa de basura, bolso, mochila, etc.): las reglas de interacción.

Lo voy a resumir, me faltaba la palabra aquí:

Los flujos son colas generalmente almacenadas en un búfer que contiene cualquier clase de datos.

(Ahora, como todos sabemos qué son las colas, no hay necesidad de explicar esto más).