Streams API
The Streams API in BanglaCode enables efficient processing of large amounts of data by breaking it into smaller chunks. Instead of loading entire files or datasets into memory at once, streams allow you to process data piece by piece, making your applications more memory-efficient and responsive.
Quick Start
// Create a writable stream
dhoro stream = stream_writable_srishti();
// Write data to stream
stream_lekho(stream, "Hello ");
stream_lekho(stream, "World!");
// Close stream
stream_bondho(stream);
dekho("Data:", buffer_text(buffer_theke(stream.Buffer)));Core Concepts
Readable Streams (স্ট্রীম পড়ার)
Readable streams represent a source of data that you can read from chunk by chunk. They're ideal for processing large files or data sources without loading everything into memory.
Writable Streams (স্ট্রীম লেখার)
Writable streams represent a destination where you can write data chunk by chunk. They're perfect for creating files, sending data over networks, or any operation that produces data incrementally.
Event-Driven Processing
Streams emit events (data, end, error) that you can listen to, enabling reactive data processing patterns. This makes streams perfect for real-time data processing and transformations.
Backpressure Management
Streams automatically handle backpressure using the high water mark, preventing memory overflow when the producer is faster than the consumer. Default high water mark is 16KB.
API Reference
stream_readable_srishti(highWaterMark?)
Creates a new readable stream.
Parameters:
highWaterMark(optional): Maximum buffer size in bytes (default: 16384)
Returns:
Stream object with type "readable"
dhoro stream = stream_readable_srishti();
dhoro largeStream = stream_readable_srishti(65536); // 64KB bufferstream_writable_srishti(highWaterMark?)
Creates a new writable stream.
Parameters:
highWaterMark(optional): Maximum buffer size in bytes (default: 16384)
Returns:
Stream object with type "writable"
dhoro stream = stream_writable_srishti();
dhoro customStream = stream_writable_srishti(32768); // 32KB bufferstream_lekho(stream, data)
Writes data to a writable stream. Triggers "data" event handlers if registered.
Parameters:
stream: Writable stream objectdata: String or Buffer to write
Returns:
True if buffer is below high water mark, false otherwise
dhoro stream = stream_writable_srishti();
stream_lekho(stream, "Hello World");
stream_lekho(stream, buffer_theke([72, 105])); // Write bufferstream_poro(stream, size?)
Reads data from a readable stream.
Parameters:
stream: Readable stream objectsize(optional): Number of bytes to read (default: all available)
Returns:
Buffer containing the read data, or null if stream is ended
dhoro stream = stream_readable_srishti();
dhoro data = stream_poro(stream); // Read all
dhoro chunk = stream_poro(stream, 100); // Read 100 bytesstream_bondho(stream)
Closes a stream, preventing further writes or reads. Triggers "end" event handlers.
Parameters:
stream: Stream object to close
dhoro stream = stream_writable_srishti();
stream_lekho(stream, "Final data");
stream_bondho(stream); // Close streamstream_shesh(stream)
Signals that a readable stream has ended (no more data will be written to it). Triggers "end" event handlers.
Parameters:
stream: Readable stream to end
dhoro stream = stream_readable_srishti();
// ... produce data ...
stream_shesh(stream); // Signal end of datastream_pipe(readable, writable)
Pipes data from a readable stream to a writable stream, automatically handling backpressure.
Parameters:
readable: Source readable streamwritable: Destination writable stream
dhoro source = stream_readable_srishti();
dhoro destination = stream_writable_srishti();
stream_pipe(source, destination);stream_on(stream, eventName, handler)
Registers an event handler for stream events (data, end, error).
Parameters:
stream: Stream objecteventName: Event name ("data", "end", or "error")handler: Function to call when event occurs
dhoro stream = stream_writable_srishti();
stream_on(stream, "data", kaj(chunk) {
dekho("Received:", chunk);
});
stream_on(stream, "end", kaj() {
dekho("Stream ended");
});
stream_on(stream, "error", kaj(err) {
dekho("Error:", err);
});Real-World Examples
Example 1: Large File Processing
Process a large file in chunks instead of loading it all into memory:
// Process large log file line by line
dhoro logStream = stream_writable_srishti();
dhoro errorCount = 0;
dhoro warningCount = 0;
// Register data handler to process chunks
stream_on(logStream, "data", kaj(chunk) {
dhoro lines = bibhajan(chunk, "\n");
ghuriye (dhoro i = 0; i < dorghyo(lines); i = i + 1) {
dhoro line = lines[i];
jodi (khuje(line, "ERROR") != mittha) {
errorCount = errorCount + 1;
} nahole jodi (khuje(line, "WARNING") != mittha) {
warningCount = warningCount + 1;
}
}
});
// Handle end of stream
stream_on(logStream, "end", kaj() {
dekho("Processing complete!");
dekho("Errors:", errorCount);
dekho("Warnings:", warningCount);
});
// Read file and write to stream in chunks
dhoro content = poro("large_log.txt");
dhoro chunkSize = 8192; // 8KB chunks
ghuriye (dhoro i = 0; i < dorghyo(content); i = i + chunkSize) {
dhoro end = i + chunkSize;
jodi (end > dorghyo(content)) {
end = dorghyo(content);
}
dhoro chunk = angsho(content, i, end);
stream_lekho(logStream, chunk);
}
stream_bondho(logStream);Example 2: Data Transformation Pipeline
Create a pipeline to transform and filter data in real-time:
// Transform and filter data pipeline
dhoro inputStream = stream_writable_srishti();
dhoro outputStream = stream_writable_srishti();
dhoro transformedCount = 0;
// Transform: uppercase + filter (length > 5)
stream_on(inputStream, "data", kaj(chunk) {
dhoro words = bibhajan(chunk, " ");
dhoro transformed = [];
ghuriye (dhoro i = 0; i < dorghyo(words); i = i + 1) {
dhoro word = words[i];
// Filter: only process words longer than 5 chars
jodi (dorghyo(word) > 5) {
dhoro upper = boro_hater(word);
transformed = dhaaka(transformed, upper);
transformedCount = transformedCount + 1;
}
}
// Write transformed data to output
jodi (dorghyo(transformed) > 0) {
dhoro result = joro(transformed, " ");
stream_lekho(outputStream, result + " ");
}
});
// Handle output stream data
stream_on(outputStream, "data", kaj(chunk) {
dekho("Transformed:", chunk);
});
// Handle completion
stream_on(inputStream, "end", kaj() {
stream_bondho(outputStream);
dekho("Transformation complete!");
dekho("Processed words:", transformedCount);
});
// Process input data
dhoro input = "hello world banglacode programming language";
stream_lekho(inputStream, input);
stream_bondho(inputStream);Example 3: Network Data Streaming
Stream data from network to file efficiently:
// Download and process data in streaming fashion
proyash kaj downloadAndProcess() {
dhoro outputStream = stream_writable_srishti();
dhoro bytesProcessed = 0;
// Monitor data as it arrives
stream_on(outputStream, "data", kaj(chunk) {
bytesProcessed = bytesProcessed + dorghyo(chunk);
// Show progress every 10KB
jodi (bytesProcessed % 10240 == 0) {
dekho("Downloaded:", bytesProcessed, "bytes");
}
});
// Handle completion
stream_on(outputStream, "end", kaj() {
dekho("Download complete!");
dekho("Total bytes:", bytesProcessed);
});
// Simulate network data (in real app, use HTTP client)
dhoro data1 = "First chunk of data...";
dhoro data2 = "Second chunk of data...";
dhoro data3 = "Third chunk of data...";
// Write chunks as they arrive
stream_lekho(outputStream, data1);
opekha ghumaao(100);
stream_lekho(outputStream, data2);
opekha ghumaao(100);
stream_lekho(outputStream, data3);
stream_bondho(outputStream);
// Save to file
lekho("downloaded.txt", buffer_text(buffer_theke(outputStream.Buffer)));
}
downloadAndProcess();Best Practices
✅ DO: Always Close Streams
Always close streams when you're done with them to free resources. Use stream_bondho() or stream_shesh() to properly terminate streams.
✅ DO: Handle Events
Register handlers for "data", "end", and "error" events to create robust stream processing. This makes your code reactive and easier to maintain.
✅ DO: Use Appropriate Buffer Sizes
Set high water marks based on your data size. Default is 16KB, but adjust for large files (64KB-1MB) or small packets (4KB-8KB) for optimal performance.
✅ DO: Process Data in Chunks
Break large operations into smaller chunks. This prevents memory overflow and keeps your application responsive while processing large datasets.
❌ DON'T: Write to Closed Streams
Attempting to write to a closed stream will result in an error. Always check stream state or handle errors properly in production code.
❌ DON'T: Ignore Backpressure
Respect the return value of stream_lekho(). If it returns false, the buffer is full - pause writes until drained to avoid memory issues.
❌ DON'T: Mix Sync and Async
Don't mix synchronous file reads with asynchronous stream processing. Keep your data flow consistent - either all sync or all async.
❌ DON'T: Load Everything First
Avoid loading entire files into memory before streaming. That defeats the purpose! Use streams from the start for true streaming performance.
Performance Tips
Optimal Chunk Sizes
For file I/O: 8KB-64KB chunks work best. For network data: 4KB-16KB. For large datasets: 64KB-1MB. Test your specific use case to find the sweet spot.
Memory Efficiency
Streams keep memory usage constant regardless of data size. A 10GB file uses only ~16KB RAM when processed with default streams - that's a 625,000x improvement!
Parallel Processing
Combine streams with Worker Threads for parallel data processing. Each worker can process its own stream for maximum throughput.
Pipeline Efficiency
Use stream_pipe() to create efficient data pipelines. The piping mechanism handles backpressure automatically, optimizing throughput.
Common Patterns
Pattern 1: Transform Stream
// Create reusable transform stream
kaj transformStream(inputStream, transformFn) {
dhoro outputStream = stream_writable_srishti();
stream_on(inputStream, "data", kaj(chunk) {
dhoro transformed = transformFn(chunk);
stream_lekho(outputStream, transformed);
});
stream_on(inputStream, "end", kaj() {
stream_bondho(outputStream);
});
ferao outputStream;
}
// Usage
dhoro input = stream_writable_srishti();
dhoro output = transformStream(input, kaj(data) {
ferao boro_hater(data); // Uppercase transform
});Pattern 2: Buffered Reader
// Read file in fixed-size chunks
kaj readInChunks(filepath, chunkSize, callback) {
dhoro content = poro(filepath);
dhoro stream = stream_writable_srishti();
stream_on(stream, "data", callback);
ghuriye (dhoro i = 0; i < dorghyo(content); i = i + chunkSize) {
dhoro end = i + chunkSize;
jodi (end > dorghyo(content)) {
end = dorghyo(content);
}
stream_lekho(stream, angsho(content, i, end));
}
stream_bondho(stream);
}
// Usage
readInChunks("data.txt", 1024, kaj(chunk) {
dekho("Processing chunk:", dorghyo(chunk), "bytes");
});Pattern 3: Stream Aggregator
// Aggregate stream data
kaj aggregateStream(stream, reduceFn, initialValue) {
dhoro accumulated = initialValue;
stream_on(stream, "data", kaj(chunk) {
accumulated = reduceFn(accumulated, chunk);
});
stream_on(stream, "end", kaj() {
dekho("Final result:", accumulated);
});
}
// Usage: Count total characters
dhoro stream = stream_writable_srishti();
aggregateStream(stream, kaj(total, chunk) {
ferao total + dorghyo(chunk);
}, 0);
stream_lekho(stream, "Hello ");
stream_lekho(stream, "World");
stream_bondho(stream);Streams vs Regular I/O
❌ Without Streams (Bad for Large Files)
// Loads entire 10GB file into memory!
dhoro content = poro("huge.log");
dhoro lines = bibhajan(content, "\n");
dhoro errors = 0;
ghuriye (dhoro i = 0; i < dorghyo(lines); i = i + 1) {
jodi (khuje(lines[i], "ERROR") != mittha) {
errors = errors + 1;
}
}
dekho("Errors:", errors);
// Memory usage: 10GB+
// Time: Very slow (disk → RAM all at once)✅ With Streams (Optimal)
// Processes 10GB file with only 16KB RAM!
dhoro stream = stream_writable_srishti();
dhoro errors = 0;
stream_on(stream, "data", kaj(chunk) {
dhoro lines = bibhajan(chunk, "\n");
ghuriye (dhoro i = 0; i < dorghyo(lines); i = i + 1) {
jodi (khuje(lines[i], "ERROR") != mittha) {
errors = errors + 1;
}
}
});
// ... write chunks to stream ...
// Memory usage: ~16KB constant
// Time: Much faster (streaming)Related APIs
Summary
The Streams API in BanglaCode provides a powerful and memory-efficient way to process large amounts of data. By breaking data into smaller chunks and processing them incrementally, streams enable you to build scalable applications that handle files and datasets of any size.
Key benefits:
- Memory Efficiency: Process gigabytes of data with only kilobytes of RAM
- Performance: Start processing immediately without waiting for entire files to load
- Backpressure: Automatic flow control prevents memory overflow
- Event-Driven: React to data as it arrives for real-time processing
- Composability: Chain streams together to create data processing pipelines
Use streams whenever you're working with large files, network data, or any scenario where you want to process data incrementally rather than all at once.