No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Streams

25/31
Recursos

Aportes 110

Preguntas 27

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Mi aporte de como lo veo:

** Stream**
Podría decirse que un Stream es el proceso de ir consumiendo datos al tiempo en que se reciben. Por ejemplo, cuando vemos un video en Youtube estamos consumiendo datos por medio de streaming (readable stream, porque solo podemos ver los videos mas no editarlos) ya que lo vemos al mismo tiempo en que este se está descargando. de lo contrario habría que esperar a que se descargue el video por completo para poder verlo.

buffer
Si en el caso anterior, mientras vemos el video, fallara el internet, así sea por un segundo, la reproducción se pararía instantáneamente. Pero sabemos que en realidad no es así, el video continúa reproduciéndose por un tiempo mas. Esto es gracias a la implementación de un buffer el cuál es un espacio en memoria ram en donde la información proveniente del servidor llega por fragmentos (chunks), para luego ser consumido, y como ese almacenamiento de datos en el buffer se hace a bajo nivel, de forma binaria, el proceso es mucho mas rápido de lo que se consume. Es por eso que cuando reproducimos un video en Youtube vemos que este se carga mas rápido. (dependiendo del ancho de banda claro está)

intentaré explicarlo para ver si se entiende de mejor manera que wea pasa en esta parte del código

const Transform = stream.Transform;

lo que se hace aquí es crear una constante que va a contener la clase Transform, pero… que es lo que hace Transform?.
pues básicamente lo que hace es transformar la secuencia de entrada para que la secuencia de salida sea una diferente. EJ: ( no falta el weon que se lo olvida que las iniciales de los nombres van en Mayúsculas, sin embargo tu quieres asegurarte que los nombres en tu pagina web, la Inicial aparezca en Mayúscula. entonces es ahí donde ocupas el Transform para que la secuencia de entrada la puedas cambiar y produzca una secuencia de salida diferente.)


Bien que aquí prácticamente estas diciendo que sera en esta función será donde ejecutaras la transformación. al colocar Tranform.call(this) estas iniciando el llamado a la tranformacion de tu secuencia datos. y al colocar this estas diciendo que se hará dentro del método Mayus

function Mayus(){
    Transform.call(this);
}

dicho esto pasemos a lo siguiente…


bien acá por lo que busque y encontré.(porque el que busca encuentra) lo que hace util.inherits(Mayus,Transform); es crear una instancia de la clase Transform y estableciéndolo como prototipo a la función Mayus, tambien adjuntando el EventEmmitter. es decir el Transform.Call(this).
de modo que cada vez que se crea una instancia de la funcion Mayus se ejecutara el fichero.

en pocas palabras para el que sepa PHP o JAVA . es como llamar al metodo super()

util.inherits(Mayus,Transform);

CABE RECALCAR QUE NODE NO RECOMIENDA USAR ESTA FUNCIÓN


bueno bueno que tenemos acá.
pero miren justo Mayus.prototype._transform fue posible gracias a la función de util.inherits(Mayus,Transform) que establecía la clase Transform como prototipo de la función Mayus.

PERO QUE SIGNIFICA ._transform ?
bueno básicamente significa que la transformación que tu harás podrá ser personalizada, así es(como mi redacción). es decir que tu veras que cambio o que transformación le harás a la secuencia de datos que estas recibiendo como entrada.

Mayus.prototype._transform=function(chunk,codifi,callback){
     chunkMayus = chunk.toString().toUpperCase();
     this.push(chunkMayus);
     callback();
}

pasemos a lo siguiente…


bueno y por ultimo que sucede al final. pues simple
creas una instancia de la funcion Mayus

y bueno por ultimo lo que hace pipe() es limitar el almacenamiento en el buffer para que no haya una sobresaturacion a la hora se pasar la secuencia de los datos


var mayus = new Mayus();

readablesStream.pipe(mayus).pipe(process.stdout);

BUENO RECALCO QUE ESTO LO DESCRIBÍ CON MIS PROPIAS PALABRAS, si hay algo en lo que me equivoco al mencionar pues que comente para que así sepamos bien el error y entendamos bien el concepto

La clase no fue muy provechosa ya que hubo muchos conceptos que no se explicaron antes (ni tampoco en los cursos de Javascript) y que esta vez se usaron prácticamente sin explicación.

inherits
__transform
.pipe
.call

Saludos, creo que el profesor no entiende muy bien el codigo de la clase, es por eso que no explico muchas partes, creo que es posible simplificar el codigo para que sea mas entendible para todos los estudiantes y no tengan que preocuparse por cosas que no tienen que ver con streams como el prototipo, inherits y etc.

Hay una forma mas simple de escribir este transform:

const { Transform } = require("stream");
const { createReadStream } = require("fs");

const upperCaseTransform = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

const readableStream = createReadStream(__dirname + "/example.txt");

readableStream.pipe(upperCaseTransform).pipe(process.stdout);

Les comparto un sandbox donde pueden verlo funcionando en vivo https://codesandbox.io/s/node-js-forked-5qiff?file=/src/index.js:0-373

Me parece que se complicó demasiado para esta transformación, hizo muchas cosas rápidamente con explicaciones muy leves y no se entendió nada desde que empezó a hacer el Transform!

Streams


Un stream es el proceso de ir consumiendo datos al tiempo que se están recibiendo. En palabras del profesor, es el paso de datos entre un punto y otro.

const fs = require('fs')

let data = ''

let readableStream = fs.createReadStream(__dirname + '/input.txt')

readableStream.setEncoding('UTF8')
readableStream.on('data', chunk => data += chunk)

readableStream.on('end', () => console.log(data))

En estos casos podemos escribir en buffer de la salida del sistema, process.stdout es un buffer de escritura en que empieza a trabajar para generar todo esto.

process.stdout.write('hola')
process.stdout.write('que')
process.stdout.write('tal')

Para usar los streams, podemos usarlos de la siguiente forma

const Transform = stream.Transform

function Upper() {
    Transform.call(this)
}

util.inherits(Upper, Transform)

Upper.prototype._transform = function (chunk, codif, cb) {
    chunkUpper = chunk.toString().toUpperCase()

    this.push(chunkUpper)
    cb()
}

let upper = new Upper()

readableStream
    .pipe(upper)
    .pipe(process.stdout)

Las Streams son colecciones de datos, como matrices o cadenas. La diferencia es que las transmisiones pueden no estar disponibles de una vez y no tienen que caber en la memoria. Esto hace que las transmisiones sean realmente poderosas cuando se trabaja con grandes cantidades de datos, o datos que provienen de una fuente externa o un fragmento a la vez.

const fs = require('fs');
const server = require('http').createServer();

server.on('request', (req, res) => {
  const src = fs.createReadStream('./big.file');
  src.pipe(res);
});

server.listen(8000);

Cuando un cliente solicita ese archivo grande, lo transmitimos un fragmento a la vez, lo que significa que no lo almacenamos en la memoria intermedia.

El error que tuvimos varios estaba en utilizar el this dentro de una arrow function. En ese caso la función apunta al objeto Window y no a Mayus.

Antes:

Mayus.prototype._transform = (chunk, codif, cb) => {
  chunkMayus = chunk.toString().toUpperCase();
  this.push(chunkMayus);
  cb();
}

Despues:

Mayus.prototype._transform = function (chunk, codif, cb) {
  chunkMayus = chunk.toString().toUpperCase();
  this.push(chunkMayus);
  cb();
}

En esta clase se usó funciones prototipal, he hecho un ejemplo usando las clases de es6 y quedo asi el buffer de transformacion.

/ BUFFER DE TRANSFORMACION
const Transform = stream.Transform;

function Mayus() {
  Transform.call(this)
}

util.inherits(Mayus, Transform);

Mayus.prototype._transform = function(chunk, codif, cb) {
  chunkMayus = chunk.toString().toUpperCase();
  this.push(chunkMayus)
  cb();
}

let mayus = new Mayus();

readableStream.pipe(mayus)
.pipe(process.stdout)

// Haciendolo con clase

class MayusC extends Transform {
  _transform(chunk, codif, cb){
    let chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus)
    cb();
  }
}

let mayusC = new MayusC();
readableStream.pipe(mayusC)
.pipe(process.stdout)

Solo es la parte de LEER
Dentro de poco subo la parte de escribir y la de hacer las dos cosas

Imagina que tienes un dulce enorme que transportar hacia tu casa para que tus hijos coman
Eres muy fuerte pero el dulce es demasiado grande, pero se te ocurre hacer algo traes una canasta y divides el dulce en partes llenas la canasta y envías esa canasta a tus hijos así tus hijos pueden ir comiendo los dulces que les enviaste mientras tus hijos se comen los dulces tú llenas la 2da canasta y la envías, así funciona esto

el búfer sería la canasta y streams sería el movimiento de enviar todo

Una vez sabiendo eso continuemos

Trabajaremos con archivos de texto en esta ocasión así que usaremos el módulo fs

const fs = require(‘fs’)

//Aquí estoy creando una variable que se llama readableStream
//Le decimos que habrá la dirección que indicamos y lea el input

let readableStream = fs.createReadStream(__dirname + ‘/input.txt’, ‘utf8’)

//Esto disparar un evento cada vez que recibamos datos y en el callback le decimos que queremos hacer con los datos
que van entrando
//(chuck) esto quiere decir una parte de lo que has recibido
//Podemos leer un archivo de 1GB y esperar que lea 1GB y luego nos muestre o
// Podemos decirle tráeme el chunk que ya tienes es decir si ya tienes 5mb tráelos que iré trabajando con eso

readableStream.on(‘data’, (chunk)=>{

console.log('new chunck recevid:')
console.log(chunk)

})

//Pero donde está la magia en todo esto ?
Pues verás te recomiendo que hagas el archivo input.txt y lo llenes de texto al azar 500 líneas de texto 100 lo que tú quieras

y veraz como cada vez que se llena el buffer (chunk) nos pasara al callaback donde le dijimos
okay muéstrame el avance del paquete que ya tienes de todo lo que tienes que mostrarme

Si te ayudo regale un like 😉
Te recuerdo que yo también estoy aprendiendo esto así que si tienes algo más que aportar estaría excelente

Buffer es la forma en que podemos leer los datos es su forma mas sencilla, en este caso Node transmite estos datos Buffer en binario.
Poder convertir datos a Buffer nos ayudara a la velocidad y mejorar el rendimiento de la lectura y escritura de datos, debido que se hace en el lenguaje de más bajo nivel para las maquinas.
Los streams son puntos de lectura de Buffers, con estos podemos declarar que acciones ejecutar cuando se recibe un buffer. Existen tres tipos de streams, stream de lectura, de escritura y de lectura y escritura.
Un gran ejemplo de uso de los streams es el procesamiento de archivos grandes, como imágenes o videos, ya que podemos transformar estos a buffer y a través de los streams cargarlos o guardarlos parte por parte para mejorar el rendimiento de nuestro código.

Tuve que ver diez veces el video a lo largo de una semana y por fin entendí todo jaja

Usando ES6 nos evitamos usar util.inherits y hace que sea un poco mas facil de entender

class Mayus extends stream.Transform{
  constructor(){
    super()
  }

  _transform(chunk, codif, cb){
    let chunkMayus = chunk.toString().toUpperCase()
    this.push(chunkMayus)
    cb()
  }
}

Gracias a todos por los aportes, entendí mejor la clase después de leer todos los comentarios

util.inherits está descontinuado. Pero se puede sustituir por la keyword class, de esta forma:

const Transform = stream.Transform;

class Mayus extends Transform {
    _transform(chunk, codif, cb) {
        let chunkMayus = chunk.toString().toUpperCase();
        this.push(chunkMayus);
        cb();
    }
}

let mayus = new Mayus();

readatableStream
    .pipe(mayus)
    .pipe(process.stdout)

La documentación de Util dice que es mejor usar las keywords de ES6 class y extends, ya que no habrá compatibilidad a futuro, les comparto mi solución usando esta sintaxis:

const Transform = stream.Transform

class Mayus extends Transform{
    _transform(chunk, encoding, callback) {
        const chunkMayus = chunk.toString().toUpperCase()
        this.push(chunkMayus)
        callback()
    }
}

const mayus = new Mayus()

readStream.pipe(mayus).pipe(process.stdout)

const fs = require('fs')
const stream = require('stream')
const util = require('util')

let data = '';
let readableStream = fs.createReadStream(__dirname+'/input.txt')
readableStream.setEncoding('UTF8')
readableStream.on('data',(texto)=> {
    data += texto

})

readableStream.on('end',() => {
    console.log(data)
})

// stream de escritura:
// process.stdout.write('hola')
// process.stdout.write('mundo')

const Transform = stream.Transform;
function Mayus(){
    Transform.call(this)
}
util.inherits(Mayus,Transform)

Mayus.prototype._transform = function(texto,codif,cb){
    textoMayuscula = texto.toString().toLowerCase()
    this.push(textoMayuscula)
    cb()
}
let mayus = new Mayus()
readableStream.pipe(mayus).pipe(process.stdout)

Sobre el uso de .pipe estuve investigando un poco y encontre lo siguiente que creo les puede servir de ayuda para el uso del mismo.

por ejemplo si tienen una función, donde getName es transformado a mayusculas, luego se seleccionan los prieros 6 caracteres y luego se escribe en reverso como la siguiente, se vuelve un poco complicado de leer:

reverse(get6Characters(uppercase(getName({ name: 'Buckethead' }))));
// 'TEKCUB'

el uso de .pipe lo facilita de la siguiente manera:

pipe(
  getName,
  uppercase,
  get6Characters,
  reverse
)({ name: 'Buckethead' });
// 'TEKCUB'

Es algo que de un articulo de internet y me parecio valioso compartirlo aqui pueden leer el articulo

pipe():sirve para envío de datos y formas de envío

Hola, hasta ahora excelente el curso. De este video me queda la duda de porque hay que hacer tantos trucos para usar el Stream de transformación? No parece natural. Gracias.

Lo malo de que dejan de darle mantenimiento a estos cursos es que aprendemos cosas que ya son obsoletas y pcoos nos percatamos de ello F para platzi team

Usage of util.inherits() is discouraged. Please use the ES6

SI no les quedo claro, talvez con las sintaxis de ES6 se entienda mejor, de igual forma pueden leer la documentación aquí

class Mayus extends Transform {
  _transform(chunk, codif, cb) {
    let chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    cb();
  }
}

const mayus = new Mayus();
readableStream.pipe(mayus).pipe(process.stdout);

La peor clase del curso, usó muchos conceptos y módulos con poco o cero contexto, para alguien que esta empezando esta clase sería diractamente chino, especialmente para el final

Bueno, no me quería quedar con las ganas de aprender un poco más a fondo este tema de los streams que veo es algo muy potente e importante, así que luego de un par de horas de estudio les puedo compartir lo siguiente lo más resumido y sencillo posible:
 
Stream de lectura
Un stream de lectura te permite leer datos de una fuente, como un archivo o una solicitud HTTP, y enviarlos a otro lugar, como un stream de transformación. Aquí tienes un ejemplo de cómo crear un stream de lectura para leer datos de un archivo:

let readableStream = fs.createReadStream(__dirname + '/contactos.csv'); // Para leer un archivo csv que les dejaré más abajo en el aporte
readableStream.setEncoding('utf8'); // Para esteblecer la codificación

Ya con esto pueden acceder al contenido “streameado” del archivo, sin embargo, por si se preguntaron cuál es la capacidad del buffer por defecto del stream, es de 64 KB o por si se preguntaron cómo hago para indicarle a mi stream que use otra capacidad específica, lo pueden hacer de la siguiente manera:

let readableStream = fs.createReadStream(__dirname + '/contactos.csv', {highWaterMark: 32 * 1024});

Allí le indico que lo haga cada 32 KB. Así es, la propiedad del objeto la toma en KB.
 
Stream de transformación
Un stream de transformación te permite modificar los datos que fluyen a través de él. Por ejemplo, puedes utilizar un stream de transformación para convertir un archivo CSV en un formato JSON. Aquí tienes un ejemplo de cómo crear un stream de transformación para convertir datos de formato CSV a formato JSON:

const stream = require('stream');
const toUpperTransformStream = new stream.Transform({
    transform(chunk, encoding, callback) {
        try {
            callback(null, Buffer.from(chunk.toString().toUpperCase()));
        } catch (error) {
            callback(error, chunk);
        }
    }
});

La anterior es otra manera de crear streams de transformación, me gustó más esta ya que la que usó el profe en el video usa conceptos que quizás algunos desconozcan, como herencia y prototipos en JavaScript. Aquí usamos una clase ya existente para ello (Transform).
 
Para usar el stream simplemente lo pasan como argumento de la función pipe del readableStream:

let readableStream = fs.createReadStream(__dirname + '/contactos.csv', {highWaterMark: 64 * 1024})
    .pipe(toUpperTransformStream);

No les voy a poner cómo imprimir en consola los datos del stream porque como lo enseñó el profe en el video funciona perfecto y pues es algo sencillo. Si podrían probar cómo va cambiando la impresión de cada chunck cuando juegan con el tamaño del buffer, es decir, el valor que le pasan a la propiedad highWaterMark.
 
Lo que si les voy a dejar es el contenido del archivo CSV que usé para mis pruebas, por si les interesa ✌ De tarea les queda averiguar como funciona el stream de escritura. Éxitos!

Nombre,Apellido,Edad,Teléfono
Miguel,Castillo,25,555-123-4567
Luis,Hernández,38,555-234-5678
Ana,Chávez,19,555-345-6789
Carolina,Gómez,47,555-456-7890
Pedro,Martínez,32,555-567-8901
Laura,Flores,27,555-678-9012
Javier,Rodríguez,50,555-789-0123
María,Torres,23,555-890-1234
Sara,Jiménez,41,555-901-2345
José,Pérez,36,555-012-3456
Sofía,Romero,28,555-123-4567
Daniel,Fernández,45,555-234-5678
Valentina,Sánchez,20,555-345-6789
Manuel,Alvarez,49,555-456-7890
Lucía,Méndez,31,555-567-8901
Diego,Vargas,26,555-678-9012
Ana,Hernández,23,555-123-4567
Mario,Rodríguez,40,555-234-5678
Sofía,Castro,32,555-345-6789
Pedro,Vega,26,555-456-7890
María,Juárez,44,555-567-8901
Luis,Ramírez,31,555-678-9012
Carolina,López,29,555-789-0123
Roberto,Ruiz,46,555-890-1234
Laura,Escobar,35,555-901-2345
Juan,Pérez,30,555-012-3456
Mónica,Galván,37,555-123-4567
Carlos,Flores,33,555-234-5678
Karen,García,27,555-345-6789
Jorge,Guzmán,39,555-456-7890
Diana,Santos,22,555-567-8901
César,Méndez,42,555-678-9012

Estoy en Twitter y en Instagram como @guillermoplus por si me quieren seguir. 👨‍💻
 
Espero les sirva Salu2.

Quisiera aportar el siguiente código usando el class de Javascript:

// ....
const Transform = stream.Transform;

class Mayus extends Transform {
      constructor() {
            super();
            Transform.call(this);
      }
      _transform = (chunk, codif, cb) => {
            let chunkMayus = chunk.toString().toUpperCase();
            this.push(chunkMayus);
            cb();
      };
}

// ...

A mí me sirvió para resolver un error que saltó en mi consola al intentar usar la versión de esta clase.

🙂 Saludos y muchos éxitos, colegas!

Por si se confudieron como yo al ver “util.inherits”, “_transform”
, “.call” . Y todo la implantación rara (al menos para mi), acá les dejo mi versión usando Clases ES6:

Lo que hacemos es crear una nueva clase “Mayus” que hederá de “Transform” que proviene del modulo “stream”, si no recuerdan para que sirven la funcion super dentro del constructor es para que la clase "Mayus " hederé todas las propiedades del objeto “Transform”, pero en “Mayus” cambiamos el comportamiento del metodo _transform, el cual es la funcion que va a transformar el contenido del stream por medio de una pipe. Siendo lo mas raro dentro de esta funcion el “this.push()” lo cual no es nada mas la forma de devolver una salida legible para los streams (o eso entendi de la documentacion). Aca les dejo parte de la documentacion oficial por si se perdieron con mi explicacion:


“All Transform stream implementations must provide a _transform() method to accept input and produce output. The transform._transform() implementation handles the bytes being written, computes an output, then passes that output off to the readable portion using the transform.push() method.”

Qué clase más compleja!, pero estuvo rebuena!. Tuve que usar un archivo muy grande para ver con mis propios ojos el tema de los chunks! 😄

Noté entonces que cada chunk era de aproximadamente 64kb, y ahí ya empecé a entender mejor el procedimiento.

Está super el curso!

Sintaxis con las clases de ES6

const Transform = stream.Transform;

class Mayus extends Transform {}

Mayus.prototype._transform = function (chunk, encoding, cb) {
  chunkMayus = chunk.toString().toUpperCase();
  this.push(chunkMayus);
  cb();
};

let mayus = new Mayus();

readableStream.pipe(mayus).pipe(process.stdout);

¯\_(ツ)_/¯

Este código:

const Mayus = function(){
    stream.Transform.call(this);
}
util.inherits(Mayus, stream.Transform);
Mayus.prototype._transform = function(chunk, codif, cb){
    const chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    cb();
}

Es equivalente a

const Mayus = function(){
    stream.Transform.call(this);
};
Mayus.prototype = Object.create(stream.Transform.prototype);
Mayus.prototype.constructor = Mayus;
Mayus.prototype._transform = function(chunk, codif, cb){
    const chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    cb();
}

Y equivalente a

class Mayus extends stream.Transform{
    constructor(props) {
        super(props);
    }
    _transform(chunk, codif, cb){
        const chunkMayus = chunk.toString().toUpperCase();
        this.push(chunkMayus);
        cb();
    }
}

Para cosas muy pequeñas no tiene sentido utilizar un stream, pero tú lo haz hecho en el ejemplo. Hubiese sido útil con un ejemplo apropiado al caso. Los ejemplos deben servir para ilustrar y aclarar un tema, no dar un mal ejemplo y decir “esto no tiene sentido, se usa para otra cosa”, se entiende? Para la próxima clase quizás, o si te agrade hacerte cargo y regrabar esta. Gracias.

Stream

Se refiere al paso de datos entre 2 puntos. Existen varios tipos de stream:

  • Stream de lectura: Es donde existe un origen y el stream se encarga de traer datos y podemos gestionarlos como deseemos.
  • Stream de escritura: Es donde tengo datos y mediante el stream mando datos a un destino concreto.
  • Stream de doble sentido (lectura y escritura): Cumple la función de los dos anteriores.

Stream de lectura

Para crear un stream que sea legible, se debe importar el módulo fs .

const { createReadStream } = require('fs')

Luego de esto, se debe crear obtener los datos o el archivo que contiene el buffer que se debe stremear.

let readableStream = createReadStream(`${__dirname}/input.txt`)

Se puede configurar la codificación del archivo, para no tener que acudir a métodos como toString() , sino que sea algo más orgánico.

readableStream.setEncoding('utf-8')

Utilizando los métodos del stream, se debe escuchar el evento 'data' que permite saber cuando llega nueva información, en este caso se hace una función que mande por consola lo que es obtenido de la 'data' .

readableStream.on('data', (chunk) => {
  console.log(chunk)
})

Para obtener archivos grandes de información la siguiente forma es la más adecuada para ir recibiendo los chunks y luego manejarlos.

  1. Se crea una variable que va a ir recibiendo los datos:

    let data = ''
    
  2. En la función se guarda la información que se obtiene en la variable data .

    readableStream.on('data', (chunk) => {
      data += chunk
    })
    
  3. Para saber cuando se termina de recibir la información, se hace lo siguiente.

    readableStream.on('end', () => {
      console.log(data)
    })
    

    Esto sirve cuando se trabaja con archivos muy grandes de información.

Stream de escritura

Mediante la salida estándar del sistema stdout se puede generar un buffer de escritura, pero no tiene estructura por si mismo.

process.stdout.write('Hola')
process.stdout.write('que')
process.stdout.write('tal')

/*
Output:
Holaquetal
*/

Buffer de transformación

Se debe importar el módulo stream .

const stream = require('stream')

En este caso se va a convertir un buffer de datos a mayúsculas.

  1. Se debe crear un stream de transformación mediante una clase que va a heredar de stream.Transform , esto se hace utilizando la sintaxis de EcmaScript6.

    class Mayus extends stream.Transform {
    	_transform(chunk,encode,cb) {
    		let chunkMayus = chunk.toString().toUpperCase()
    		this.push(chunkMayus)
    		cb()
    	}
    }
    
    /*
    Output:
    ESTE 
    ES 
    UN 
    ARCHIVO
    QUE 
    VAMOS 
    A 
    LEER
    */
    

En mi última aplicación tuve que desarrollar la subida de archivos de tipo pdf pero en general funciona para cualquier tipo de archivos.
En ese caso que les platico, realicé la funcionalidad con módulos de Stream.
Ustedes, ya de ante mano, realizaron sus configuraciones de Express para el desarrollo API de un backend web.

En nuestras primeras líneas, observarán una “configuración” típica de un fs para obtenera la información de recurso fs.createReadStream
En ello, se establece una comunicación con el Backen, a través de un endpoint de servicio, para obtener todo ese blob de información.
En mi caso, subí la información a FireStore para su almacenamiento.

Encontrarán el caso donde se limpía el nombrado del archivo para evitar acentos o guiones bajos y dejarlo límpio en un solo formato.
Ambos puntos, establecen la comunicación para que, cuando terminen, ambos se mencionen:

  1. Desde el cliente, ya no tengo más que subir.
  2. Desde el backend, ok (200) ya tengo todo arriba.

Este es el código del profe con unas cuantas notas explicando lo que hace cada cosa.
utilicé aportes de los compañeros en los comentarios para entenderlo un poco mejor y aca les dejo mis apuntes por si a alguien le sirve

const fs = require('fs');
const stream = require('stream');
const util = require('util');

let data = '';

//createReadStream me permite generar un stream de lectura
//en este casoestoy tomando un archivo de texto cualquiera como input
let readableStream = fs.createReadStream(__dirname + '/input.txt');

// readableStream irá recibiendo los paquetes o chunks en formato de buffer 
// y en este caso los estoy parceando a utf8
// chunk es como se llama a cada paquete o fragmento de datos que iré leyendo
readableStream.setEncoding('UTF8');

//   readableStream.on('data'...) inicia una escucha de evento en la que escucharé
//   cuando reciba la información del archivo a leer
//   luego iré añadiendo los chunks a mi variable data declarada previamente
// readableStream.on('data', function (chunk) {
//     data += chunk;
// });

//   readableStream.on('end'...) escucha a cuando se termina de recibir datos del archivo
//   de texto. en ese momento hago un consol.log y muestro el total de la data
// readableStream.on('end', function() {
//     console.log(data);
// });

//   Aquí estoy escribiendo en el buffer de la salida del sistema
//   es el ejemplo mas sencillo de stream de escritura
// process.stdout.write('hola')
// process.stdout.write('que')
// process.stdout.write('tal')

// Ya vimos stream de lectura y de escritura ahora veremos la forma media en la que
// leemos la secuencia la transformamos y volvemos a escribir

// lo que se hace aquí es crear una constante que va a contener la clase Transform,
// pero… que es lo que hace Transform?.
// transforma la secuencia de entrada para que la secuencia de salida sea una diferente.
const Transform = stream.Transform;

// en esta función será donde ejecutaras la transformación. al colocar Tranform.call(this)
// estas iniciando el llamado a la tranformacion de tu secuencia datos
// y al colocar this estas diciendo que se hará dentro del método Mayus
function Mayus() {
    Transform.call(this);
}

// util.inherits(Mayus,Transform); es crear una instancia de la clase Transform 
// y estableciéndolo como prototipo a la función Mayus, tambien adjuntando el EventEmmitter.
// es decir el Transform.Call(this).
// de modo que cada vez que se crea una instancia de la funcion Mayus se ejecutara el fichero.
// en pocas palabras para el que sepa PHP o JAVA . es como llamar al metodo super()
util.inherits(Mayus, Transform);

// le agrego una funcion personalizada a mayus (paquete, codificacion, callback)
Mayus.prototype._transform = function(chunk, codif, cb) {
    chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    cb();
}

// aqui es donde comienzo a hacer la trnasformacion, lo anterior era 
// la configuracion o codigo necesario
let mayus = new Mayus();

readableStream // entrada
    .pipe(mayus) // transformacion
    .pipe(process.stdout); //salida

    // pipe() limita el almacenamiento en el buffer para que no haya una 
    // sobresaturacion a la hora se pasar la secuencia de los datos

La implementación de ejemplo de los stream de transformación es algo engorrosa, ya que podíamos hacer lo mismo en el readableStream con un .toUpperCase() en el evento ‘data’, antes de concatenar el chunk a la variable data.

<h1>Streams<h1>

son colecciones de datos, como matrices o cadenas. La diferencia es que las transmisiones pueden no estar disponibles de una vez y no tienen que caber en la memoria. Esto hace que las transmisiones sean realmente poderosas cuando se trabaja con grandes cantidades de datos, o datos que provienen de una fuente externa o un fragmento a la vez.

<h4>Streams de lectura</h4>
const fs = require('fs');
let data = ""
let stream = fs.createReadStream (__dirname + "./archivo.txt") // importamos un archivo
stream.on("data", (chunk) => {
	console.log(chunk) // veremos el chunk que recibimos
// si son varios chunk usamos data += chunk
// podemos usar stream.setEncoding(UTF8) para convertir a sting
});
// para imprimir una vez terminado
stream.on("exit", (chunk) => {
	console.log(data)
}); // cuidado con las arrow function aquí porque this puede señala a windows
<h4>Streams de escritura</h4>
process.stdout.write("hola")
process.stdout.write("que")
process.stdout.write("tal")
// OUTPUT: holaquetal
// stdout ya es un buffer de escritura
<h4>Streams de lectura y escritura (transformación)</h4>
const stream = requiere("stream")
const transform = string.tranform // esto crea un string de tranformación 
cont util = require("util")

function mayusculator () {
	transform.call(this)
}
util.inherts(mayusculato, transform);
mayusculator.prototye.transorm = function (chunk, codif, callback) {
	chunkmayusculator = chunk.toString().tuUpperCase();
	this.push(chunkmayusculator)
callback()
}
let mayus = new mayus ()
	stream.pipe(mayus)
				.pipe(process.stdout)

La verdad no endí la ultima, solo lo copiaré quiza no entienda ahora pero mas adelante cuando aprenda nuevos conceptos sí, igualmente hay otros cursos con otros profesores que explican el mismo concepto, quizá a ellos si le puedan entender no se romapn la cabeza 😃

No entendí el motivo de utilizar 'util.inherits', cuando se podría usar simplemente Mayus.prototype = new Transform() ``` const fs = require('fs'), stream = require('stream') const const readable = fs.createReadStream(__dirname + '/texto.txt') const Transform = stream.Transform function Mayus(_this) { Transform.call(this) } Mayus.prototype = new Transform() Mayus.prototype._transform = function(chunk, codif, cb) { mayusChunk = chunk.toString().toUpperCase() this.push(mayusChunk) cb() } const mayus = new Mayus(this) readable.pipe(mayus).pipe(process.stdout) ```

Streams
Los streams son flujos de información que usamos en la transmición de datos binarios. El flujo de información que forma un stream se transmite en pedazos, mejor conocidos como chunk. Los chunk no son más que objetos de la clase Buffer

Esta clase es importantísima. Se me ocurre que podemos desarrollar filtros para audio, video, overlays de caracteres para transmisiones en vivo, codecs y más. Habrá que probar. Gracias!

Si quieren verlo en forma de clases en lugar de prototipos creo que se entiende mejor:

const fs = require('fs')
const {Transform} = require('stream')

let readableStream = fs.createReadStream(`${__dirname}/input.txt`)
readableStream.setEncoding('UTF8')

/*al colocar Tranform.call(this) estas iniciando el llamado a la tranformacion de tu secuencia datos. y al colocar this estas diciendo que se hará dentro de la clase (tomado de otro comentario)*/

class UpperCase extends Transform {
    constructor(){
        super()
        Transform.call(this)
    }

    _transform(chunk, encoding, cb) {
        let upperChunk = chunk.toString().toUpperCase()
        this.push(upperChunk)
        cb()
    }
}

//se crea la instancia de la clase
let upperCase = new UpperCase()

readableStream
    .pipe(upperCase)
    .pipe(process.stdout)

Mi aporte:
Si estas viendo este video a partir del 2022 (Yo estoy en el 2023)
No necesitas traer o importar "util"
Puedes usar la palabra calve “extends” para implementar una herencia de una clase a otra:

class Mayuscula extends Transform{}

Tambien la sobreescritura de metodos, no es necesario hacerlo con prototipos, ahora puedes colocar un metodo dentro de la clase que hereda, con el mismo nombre o firma de ese metodo que vas a sobreescribir y hacerlo desde alli, ejemplo:

class Mayuscula extends Transform{
	_transform(chunk, codif, callback){
	//code logic aqui	
	}
}

Y listo.

STREAM
Un stream es como un flujo continuo de datos que se procesan de manera secuencial, en lugar de cargar todo en la memoria al mismo tiempo. Imagina un río de información que fluye, y puedes procesar cada parte del río a medida que pasa.

En Node.js, los streams son muy útiles para manejar grandes cantidades de datos de manera eficiente. Puedes leer o escribir datos en pedazos más pequeños, lo que ahorra memoria y permite un procesamiento más rápido. Por ejemplo, cuando estás leyendo un archivo grande, puedes usar un stream para procesar los datos a medida que se van leyendo, en lugar de cargar todo el archivo en memoria de una vez.

Una consulta, veo un curso de Fundamentos, luego un Curso de Node y luego un curso Práctico, dados por el gran Carlos. El orden sería tal cual los he citado, ¿verdad?

Lo mismo tampoco estaría mal actualizarlos para ya usar clases y todo lo que trae ES6+

Un saludo y gracias.

PD: Gracias también a los compañeros como siempre por compartir.

Que horrible clase, me imagino que el tema es complejo pero aun asi falto mucha explicación , parece una clase de magia porque todo apareció de la nada

stdout: ya es un buffer de escritura

require(‘util’): permite trabajar con herencia automatico

Creo que muchos entendemos que aquí hubo herencia prototipal y demás cosas, lo confuso aquí son los métodos que se utilizaron, ya que según veo son propios de los módulos que se están requiriendo.

Considero que para entender mejor esta clase se tuvo que haber explicado al menos por encima los metodos que se usaron, tanto los de stream como los de util.

Es INCREIBLE lo bien que funciona el uncaughtException, tuve algunos errores en mi escritura de codigo, por lo tanto utilice este process con un console.error(err.message), 2 segundos mas tardes ya habia limpiado todo.
Sin lugar a dudas es increible la documentacion que nos prepara platzi para entender y mejorar!

Se puede pasar el codigo de la parte final a ECMAscript 2015 y quedaria asi.

const  { createReadStream } = require('fs')
const stream = require('stream')
let readableStream = createReadStream(__dirname + '/input.txt')

class Mayus extends stream.Transform {
    _transform(chunk, codif, cb) {
        let chunkMayus = chunk.toString().toUpperCase();
        this.push(chunkMayus);
        cb();
    }
}
let mayus = new Mayus();

readableStream
    .pipe(mayus)
    .pipe(process.stdout)

Wooow esta clase si me ha volado la cabeza, no la entendí 😦

hace mucho que a una clase no le entendia jajajajaj

Para los que se confundieron:

Básicamente necesitamos crearnos una ++clase ++que herede el funcionamiento de Tranform

(para los que saben java este concepto está más fácil)

Por lo cual

podemos borrar:

function Mayus() {
    Transform.call(this);
}
util.inherits(Mayus, Transform);

cambiarlo por :

class Mayus extends Transform {
}

esto sugieren los IDE, donde hacen mención a Ecmascript 6.

todo lo que eliminamos básicamente era un truco para que Mayus herede el Transform ()

El codigo me da error.

const fs = require('fs');
const stream = require('stream');
const util = require ('util');

 let data = '';

 let readableStream = fs.createReadStream(__dirname + '/input.txt');
 readableStream.setEncoding('UTF8');

const Transform = stream.Transform;

function Mayusculas() {
    Transform.call(this);
}

util.inherits(Mayusculas, Transform);

Mayusculas.prototype._transform = (chunk, codif, callback) => {
    chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    callback();
}

let mayus = new Mayusculas();

readableStream
    .pipe(mayus)
    .pipe(process.stdout);

El mensaje de error que arroja es este:

$ node stream.js
C:\Users\fgarcia\Platzi\FundamentosNodeJS\memoria\stream.js:36
    this.push(chunkMayus);
         ^

TypeError: this.push is not a function
    at Mayusculas._transform (C:\Users\fgarcia\Platzi\FundamentosNodeJS\memoria\stream.js:36:10)
    at Mayusculas.Transform._read (_stream_transform.js:189:10)
    at Mayusculas.Transform._write (_stream_transform.js:177:12)
    at doWrite (_stream_writable.js:435:12)
    at writeOrBuffer (_stream_writable.js:419:5)
    at Mayusculas.Writable.write (_stream_writable.js:309:11)
    at ReadStream.ondata (_stream_readable.js:728:22)
    at ReadStream.emit (events.js:223:5)
    at addChunk (_stream_readable.js:309:12)
    at readableAddChunk (_stream_readable.js:286:13)

Lo que hace es literalmente leer input.txt, despuésmodifica ese buffer la función Mayus y finalmente lo imprime al stdout.
.
Para pasar datos de un lado a otro de usa la función pipe() 😁
.
Aún así no me queda claro si todo esto se hace en un sólo stream, alguien podría decirme si sí es un solo stream?

Este video puede ser confuso ya que en JavaScript no se manejan clases, es cierto que se usa

new Mayus()

Pero en realidad es Syntactic Sugar, al final, todo en JavaScript son Prototipos y me parece que hay un curso de JavaScript aquí en Platzi en el cual explican mejor todos estos conceptos y como this se comporta diferente si se utilizan Arrow Functions.

el tranform llevándolo a un contexto real me imagino que puede servir para cambiar la definición de un vídeo o no?

Algo no hice bien, pero no se donde!

me da este error!

nodemon] clean exit - waiting for changes before restart
[nodemon] restarting due to changes...
[nodemon] starting `node stream.js`
HOLA 
EVENTSOURCE
ES UN 
ARCHIVO 
        XMLDOCUMENT

        X_0
/Applications/XAMPP/xamppfiles/htdocs/platzi master/Fundamentos de nodeJS/memoria/stream.js:24
    this.push(chunkMayus);
         ^

TypeError: this.push is not a function
    at Mayus._transform (/Applications/XAMPP/xamppfiles/htdocs/platzi master/Fundamentos de nodeJS/memoria/stream.js:24:10)
    at Mayus.Transform._read (_stream_transform.js:189:10)
    at Mayus.Transform._write (_stream_transform.js:177:12)
    at doWrite (_stream_writable.js:431:12)
    at writeOrBuffer (_stream_writable.js:415:5)
    at Mayus.Writable.write (_stream_writable.js:305:11)
    at ReadStream.ondata (_stream_readable.js:726:22)
    at ReadStream.emit (events.js:210:5)
    at addChunk (_stream_readable.js:308:12)
    at readableAddChunk (_stream_readable.js:285:13)
[nodemon] app crashed - waiting for file changes before starting...```

No se si entienda un poquito mejor la utlima parte usando clases, aquí dejo el código como lo entendí.
Transform lo me que permite es alterar alterar los datos que pasan por el stream (flujo de datos). Como en este caso pasar a mayusculas el recurre al metodo _transform para operar con los datos, el cual lo definimos para darle la funcionalidad que nosotros deseamos.

class Mayus extends Transform{
    constructor(){
        super()
        Transform.call(this);
    }
    _transform(chunk,codif,cb){
        let chunkMayus = chunk.toString().toUpperCase();
        this.push(chunkMayus);
        cb();
    }
}

me esta dando error.

Este es mi codigo

const fs = require('fs');
const stream = require('stream');
const util = require ('util');

 let data = '';

 let readableStream = fs.createReadStream(__dirname + '/input.txt');
 readableStream.setEncoding('UTF8');




const Transform = stream.Transform;

function Mayusculas() {
    Transform.call(this);
}

util.inherits(Mayusculas, Transform);

Mayusculas.prototype._transform = (chunk, codif, callback) => {
    chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    callback();
}

let mayus = new Mayusculas();

readableStream
    .pipe(mayus)
    .pipe(process.stdout);


el error que me da es este:

$ node stream.js
C:\Users\fgarcia\Platzi\FundamentosNodeJS\memoria\stream.js:36
    this.push(chunkMayus);
         ^

TypeError: this.push is not a function
    at Mayusculas._transform (C:\Users\fgarcia\Platzi\FundamentosNodeJS\memoria\stream.js:36:10)
    at Mayusculas.Transform._read (_stream_transform.js:189:10)
    at Mayusculas.Transform._write (_stream_transform.js:177:12)
    at doWrite (_stream_writable.js:435:12)
    at writeOrBuffer (_stream_writable.js:419:5)
    at Mayusculas.Writable.write (_stream_writable.js:309:11)
    at ReadStream.ondata (_stream_readable.js:728:22)
    at ReadStream.emit (events.js:223:5)
    at addChunk (_stream_readable.js:309:12)
    at readableAddChunk (_stream_readable.js:286:13)

Es la primera clase de Carlos que no me quedó claro a la primeria. pero razoné que lo que estaba haciendo era crear una clase Mayus que extiende a Transform y que sobrecarga el método _transform.

aquí mi versión con alta azúcar sintáctica.

class Mayus extends stream.Transform{
    _transform(chunk, codif, cb){
        const chunkMayus = chunk.toString().toUpperCase();
        this.push(chunkMayus);
        cb();
    }
}

let mayusc = new Mayus();

readableStream.pipe(mayusc).pipe(process.stdout);

Para los que de pronto no entendieron bien el comportamiento de _transform o inherits, aquí les dejo el mismo código escrito de otra manera para ver si lo pueden entender mejor!

const fs = require('fs');
const stream = require('stream');

let data = ''; 

let readeableStream = fs.createReadStream(`${__dirname}/practicas.js`);

readeableStream.setEncoding('UTF8');

readeableStream.on('data', datos => {
    data += datos; 
}) 

readeableStream.on('end', () => {
    console.log('Ya se termino!!!')
});

class Mayus extends stream.Transform { // Ingresa CTRL + Click en el stream.Transform para ver que en el constructor se ejecuta el método que estamos sobrescribiendo (VS Code)
    _transform(chunk) { // Y este es el método que apenas se ejecuta con el constructor
        let chunkMayus = chunk.toString().toUpperCase();
        console.log(this);
        this.push(chunkMayus);
        console.log(this);
    }
}
// El pipe básicamente es un concepto que también se ve en la consola que es pasarle información de un comando a otro para que lo utilice de argumento, si no te quedo muy claro googlea 'Pipe operators' y de pronto vas a comprenderlo mejor
readeableStream 
    .pipe(new Mayus()) // Vas a ver que el pipe va a pasarle lo que leyó como opciones del constructor!
    .pipe(process.stdout)

Les comparto esto que puede resultar una gran herramienta a lo hora de tratar de entender este tipo de cosas que a veces los profes se salta.

Si mantienen presionado la tecla Ctrl. y posicionan su cursor sobre las clases, métodos, objetos y demás en VSCode, te brinda más información sobre el mismo, por ejemplo su construcción o instanciación e incluso se subraya y vuelve hipervínculo que te lleva al Código del mismo

Al hacer esto, sobre el ‘stream’ de const Transform = stream.Transform; pude ver que stream es una clase y que Transform viene igual de otra clase.

Cuando hacer esto, y navegas por el Código, encuentras lo siguiente que ayuda a entender mejor el Transform y el _transform.

Aquí abajo el código de cada una por si les ayuda a entender mejor.

class Transform extends Duplex {
            constructor(opts?: TransformOptions);
            _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
            _flush(callback: TransformCallback): void;
        }

Con esto pude entender que no estamos nombrando cosas al aire sino más bien invocando clases o prototipos del internal de Node.

Si aportar más a esto, estaría de lujo ya que siento que si quedó poco claro.

Les dejo el código por si alguien se perdió sobre el final como yo 😁

const fs = require("fs");
const stream = require("stream");
const util = require("util");

let data = "";

let readableStream = fs.createReadStream(__dirname + "/input.txt")

readableStream.setEncoding("utf-8");

// readableStream.on("data", function (chunk) {
// 	console.log(chunk);
// });

// readableStream.on("end", function() {
// 	console.log(data);
// });

// process.stdout.write("Hola");
// process.stdout.write("que");
// process.stdout.write("tal");

const Transform = stream.Transform;

function Mayus() {
	Transform.call(this);
}

util.inherits(Mayus, Transform);

Mayus.prototype._transform = function(chunk, codif, cb) {
	chunkMayus = chunk.toString().toUpperCase();
	this.push(chunkMayus);
	cb();
}

let mayus = new Mayus();

readableStream
	.pipe(mayus)
	.pipe(process.stdout) 
/* Streams es el paso de datos de un lado a otro */

const fs = require('fs');
const stream = require('stream');
const util = require('util');

let data = '';
/* 
Con esto empezamos a abrir los datos de un archivo */

let reasableStream = fs.createReadStream(__dirname + '/input.txt');

/* reasableStream.on('data', function (chunk) {
    console.log(chunk);
    console.log(chunk.toString());
}) */
/* Esta es una forma de pasar la informacion de hexa a formato UFT8 */
reasableStream.setEncoding('UTF8');

/* Si tenemos un archivo muy pero muy grande podemos enviar toda la informacion a que se procese primero y cuando este todo listo mostralo, se hace asi: */

/* reasableStream.on('data', function (chunk) {
   data += chunk;
})

reasableStream.on('end', function () {
    console.log(data);
    console.log('Soy yo');
 }) */

/* la diferencia de hacer esto se nota en memoria y para cosas grandes como suvir  un archivo de 20GB  a internet */

/* Esto es un steam de escritura */

/* process.stdout.write('Hola')
process.stdout.write('que')
process.stdout.write('tal') */


/* Esto es un buffer de lectura y escritura lee del fichero pasa a mayuscula y escribe */

const Transform = stream.Transform;

function Mayus() {
    Transform.call(this);
}
util.inherits(Mayus, Transform);

Mayus.prototype._transform = function(chunk, codif, cb) {
    chunkMayus = chunk.toString().toUpperCase();
    this.push(chunkMayus);
    cb();
}

let mayus = new Mayus();

reasableStream
    .pipe(mayus)
    .pipe(process.stdout);

Un chunk es un conjunto de buffers? O es lo mismo?

que es chunk?

Aqui esta la documentacion de node sobre Transform y algunas alternativas de como es posible escribirlos https://nodejs.org/docs/latest/api/stream.html#stream_implementing_a_transform_stream

Intente hacer el ejecicio con ARROW FUNCTIONS:

 () => {}

No pude por que marcaba error. Que raro.

Aquí les dejo una lectura sobre los Streams en NodeJS

**STREAMS** *Los **streams** en* **Node.js** *son una **abstracción** **poderosa** y **eficiente** para **trabajar** con **datos** que se **transmiten** de **forma** **continua**, permitiendo el **procesamiento** de **grandes** **volúmenes** de **datos sin cargarlos completamente** en la **memoria**. **Existen varios tipos** de **streams**, como los de **lectura**, **escritura**, **dúplex*** (que combinan lectura y escritura) *y de **transformación*** (que pueden modificar o transformar los datos mientras pasan a través de ellos)*. **Utilizando** **streams**, las **aplicaciones*** **Node.js** *pueden **leer** y **escribir datos** de **archivos**, **manipular** **datos** en **red** y **procesar** **flujos** en **tiempo** **real** de manera **eficiente**. Este **enfoque** es **especialmente** **útil** para **tareas** como la **manipulación** de **archivos** **grandes**, la **transmisión** de **datos** en **tiempo** **real** y la **implementación** de **pipelines** de **procesamiento** de **datos**. La* **API** *de **streams** de* **Node.js** ***proporciona** **métodos** y **eventos** que **facilitan** el **manejo** de **errores**, la **gestión** del **flujo** de **datos** y la **integración** con **otras** **partes** del ecosistema de* **Node.js*.***
Sinceramente esta clase no se entendio fue nada. Pero investigando encontre algo que me ayudo a entender al menos el concepto de los streams. En Node.js, los streams son una forma eficiente de manejar la lectura y escritura de datos, especialmente cuando trabajas con archivos o flujos de datos grandes. En lugar de cargar todo el contenido de un archivo en la memoria antes de procesarlo, los streams permiten leer y escribir datos en pequeños fragmentos, lo que ahorra memoria y mejora el rendimiento. Hay varios tipos de streams en Node.js: 1. **Readable Streams (Flujos de Lectura)**: Permiten leer datos de una fuente, como un archivo o una solicitud HTTP. Puedes consumir estos datos a medida que están disponibles, en lugar de esperar a que se cargue todo el archivo en memoria. 2. **Writable Streams (Flujos de Escritura)**: Permiten escribir datos en un destino, como un archivo o una respuesta HTTP. Los datos se escriben a medida que están disponibles, lo que es útil para enviar grandes volúmenes de datos o procesar datos en tiempo real. 3. **Duplex Streams (Flujos Dúplex)**: Son streams que pueden ser tanto de lectura como de escritura. Son útiles cuando necesitas una comunicación bidireccional, como en el caso de una conexión de red. 4. **Transform Streams (Flujos de Transformación)**: Son una subclase de los flujos dúplex que permiten modificar o transformar los datos a medida que se pasan a través de ellos. Son útiles para tareas como la compresión, el cifrado o la conversión de formatos.
En resumen, los **buffers** son como contenedores de datos temporales, mientras que los **streams** son como canales de flujo de datos continuos que te permiten trabajar con datos de manera incremental, lo que es muy útil para manejar grandes volúmenes de información de manera eficiente en Node.js.
En 2023 (node 20), el código sería: *const* *Transform* = *stream*.*Transform*; *const* mayus = new *Transform*({    transform(*chunk*,*encodig*,*callback*){        this.push(*chunk*.toString().toUpperCase())        callback()    }}) readbleStream.pipe(mayus).pipe(process.stdout);

Ya llevo como 3 años programando con node. Entendi lo que hizo el profe con los pipes y creando una “Clase” que hereda de Transform. Pero igual siento que toda la explicacion fue muy apresurada y no se entendio muy bien que hace Transform en si.

Hola aqui una modificacion del codigo porque util.inherits ya esta deprecado

const fs = require('fs');
const stream = require('stream');

let readableStream = fs.createReadStream(__dirname + '/readme.md');
readableStream.setEncoding('UTF8');
readableStream.on('data', function (chunk) {
    console.log(chunk);
    // console.log(chunk.toString()); // ya no es necesario si se modifica el Encoding
});


class Upper extends stream.Transform {

    _transform(chunk, encoding, callback) {
        this.chunkUpper = chunk.toString().toUpperCase();
        this.push(this.chunkUpper);
        callback();
    }
}

let upper = new Upper();
readableStream.pipe(upper)
    .pipe(process.stdout)

Este es un ejemplo de stream de escritura

const fs = require('fs');

// Creamos un Stream de escritura
const writeStream = fs.createWriteStream('output.txt');

// Escribimos en el Stream de escritura
writeStream.write('Hola, ');
writeStream.write('Mundo!');
writeStream.write('\n');

// Cerramos el Stream de escritura
writeStream.end();

console.log('Archivo creado exitosamente!');

Este código no funciona.

Otra forma de transformar el chunk es restándole 32 (al chunk), porque a es 97 en binario y A es 65 en binario

//  Streams

//  Se utiliza para captar la informacion recibida en partes "Principalmente usada para
//  grandes cantidades". Y modificarla dependiendo del uso

//fs ya marcado antes con require
const stream = require('stream');
const util = require('util')
//  básicamente lo que hace es transformar la secuencia de entrada para que la secuencia de salida sea una diferente
const Transform = stream.Transform;

let data = '';

let readableStream = fs.createReadStream(__dirname + '/input.txt')
readableStream.setEncoding('utf8')


// readableStream.on('data', function (chunk) {
//     data += chunk;
// })

// readableStream.on('end', function(){
//     console.log(data);
// })

// process.stdout.write('abc')

// esta función será donde ejecutaras la transformación. al colocar Tranform.call(this) estas iniciando el llamado
//  a la tranformacion de tu secuencia datos. y al colocar this estas diciendo que se hará dentro del método Mayus
// function Mayus(){
//     Transform.call(this);
// }
// // es crear una instancia de la clase Transform y estableciéndolo como prototipo a la función Mayus.
// util.inherits(Mayus, Transform);

// // Se podra ver que cambio o que transformación le harás a la secuencia de datos que estas recibiendo como entrada.
// Mayus.prototype._transform = function(chunk, codif, cb){
//     chunkMayus = chunk.toString().toUpperCase()
//     this.push(chunkMayus);
//     cb();
// }

// La version nueva utilizando constructor.

class Mayus extends Transform {
      constructor() {
            super();
            Transform.call(this);
      }
      _transform = (chunk, codif, cb) => {
            let chunkMayus = chunk.toString().toUpperCase();
            this.push(chunkMayus);
            cb();
      };
}


// creas una instancia de la funcion Mayus
let mayus = new Mayus();

// es limitar el almacenamiento en el buffer para que no haya una sobresaturacion a la hora se pasar la secuencia de los datos
readableStream
    .pipe(mayus)
    .pipe(process.stdout)
Mala la clase

Me explotó la cafetera con esta clase jajaja

La clase fue muy didactica

Esta tema no es sencillo. Podría dar para un curso entero.

Alguien sabe que sig que algo empiece con mayuculas? Por ejemplo Transform

La verdad de esta clase solo entendí hasta que hizo la modificación de ahí para adelante se fue enredando como un callback hell xD

quien seria this en este caso??

Podría decirse que un Stream es el proceso de ir consumiendo datos al tiempo en que se reciben

Me perdí y hasta me saco error jajajajaja íbamos bien pero aquí varios conceptos estuvieron bastantes complejos.

Me surge la duda, ¿se podría utilizar class de ES6 para este caso?

Estaría muy bueno que añadan un video luego de este donde se nos proporcione en archivos un file extensivo y mandarlo a una variable en chunks para notar esa diferencia.

En qué caso usar streams

Streams pasar algo de un lugar a otro

A mi me imprime directo en UTF-8 sin que lo especifique o lo cambie a string 😮 Alguien sabe pq? Tal vez nueva versión