{"componentChunkName":"component---src-components-blog-template-js","path":"/blog/2023-08-16-nodejs-streams/","result":{"data":{"markdownRemark":{"frontmatter":{"title":"Node.js Streams","date":"2023-08-16"},"html":"<p>When working with large files or large amounts of data in Node.js, loading everything into memory at once is not practical. If we try to read a 2GB file using <code class=\"language-text\">fs.readFile</code>, the entire file gets loaded into memory, which can crash the application or slow it down significantly. Streams solve this by processing data in small chunks.</p>\n<h3>What Are Streams</h3>\n<p>A stream is a sequence of data that is made available over time. Instead of waiting for all the data to be ready, we process it piece by piece as it arrives. This is similar to watching a video online. We do not wait for the entire video to download before watching it. The video plays while the rest is still loading.</p>\n<p>Node.js has four types of streams: Readable, Writable, Duplex, and Transform.</p>\n<h3>Readable Streams</h3>\n<p>A readable stream is a source of data. We can read from it chunk by chunk. A common example is reading a file:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const fs = require(\"fs\");\n\nconst readStream = fs.createReadStream(\"largefile.txt\", { encoding: \"utf8\" });\n\nreadStream.on(\"data\", (chunk) => {\n  console.log(\"Received chunk:\", chunk.length, \"bytes\");\n});\n\nreadStream.on(\"end\", () => {\n  console.log(\"Finished reading\");\n});</code></pre></div>\n<p>The <code class=\"language-text\">data</code> event fires every time a new chunk is available. The default chunk size is 64KB, but we can change it with the <code class=\"language-text\">highWaterMark</code> option.</p>\n<h3>Writable Streams</h3>\n<p>A writable stream is a destination where we can send data. Writing to a file is a common example:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const writeStream = fs.createWriteStream(\"output.txt\");\n\nwriteStream.write(\"First line\\n\");\nwriteStream.write(\"Second line\\n\");\nwriteStream.end(\"Last line\\n\");</code></pre></div>\n<h3>Piping</h3>\n<p>The real power of streams comes from piping, which connects a readable stream to a writable stream. Data flows from the source to the destination automatically:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const readStream = fs.createReadStream(\"input.txt\");\nconst writeStream = fs.createWriteStream(\"output.txt\");\n\nreadStream.pipe(writeStream);</code></pre></div>\n<p>This copies the file from input to output without loading the entire file into memory.</p>\n<h3>Transform Streams</h3>\n<p>Transform streams sit between a readable and writable stream, modifying the data as it passes through. A practical example is compressing a file:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const zlib = require(\"zlib\");\nconst gzip = zlib.createGzip();\n\nfs.createReadStream(\"input.txt\")\n  .pipe(gzip)\n  .pipe(fs.createWriteStream(\"input.txt.gz\"));</code></pre></div>\n<p>The data flows from the file, through the gzip transform, and into the compressed output file.</p>\n<h3>When to Use Streams</h3>\n<p>Streams are useful whenever we deal with large data. Reading or writing large files, processing CSV or JSON data row by row, handling HTTP request and response bodies for file uploads or downloads, and piping data between services. For small data that fits comfortably in memory, the simpler <code class=\"language-text\">readFile</code> and <code class=\"language-text\">writeFile</code> methods are fine. But when the data size is unpredictable or potentially large, streams are the safer choice.</p>"}},"pageContext":{"slug":"/2023-08-16-nodejs-streams/"}},"staticQueryHashes":[]}