Working with Streams
The stream API moves binary data and decoded Unicode text through a uniform set of bounded operations. It gives files, standard I/O, temporary files, memory-backed output, and custom data sources the same vocabulary. Every public operation has a configured time bound, reads distinguish data from timeout and normal completion, and writes accept a complete request or none of it.
The following sections map the complete API by task. Use them to identify the part you need, then follow the linked topic for the detailed contracts and executable examples.
Creating Streams and Managing Ownership
Start here when you need to choose a stream type, open a file, configure it, or decide how a component should receive a stream. The four central interfaces separate raw bytes from decoded text and input from output:
Data |
Read |
Write |
|---|---|---|
Exact binary representation |
||
Decoded Unicode text |
File streams are opened through Path::content() and returned with shared
ownership.
Read Creating Streams and Managing Ownership for the opening methods, path and stream settings, explicit cleanup, and best practices for
passing the narrowest useful interface.
Byte Input and Output
Use byte streams for file formats, network frames, checksums, compressed content, or any operation where every byte is significant. They support bounded reads into spans, retained exact reads, explicitly limited aggregate reads, atomic writes, and endian-aware integer operations.
If you are deciding how to handle a short read, resume after a timeout, cap memory use, or retry a write without duplicating data, continue with Byte Input and Output.
Text Input, Output, and Encoding
Text streams place the encoding boundary below your application logic. They decode complete Unicode code points, read lines and bounded text blocks, write strings and formatted values, and can capture generic text output in memory.
Use this API for configuration files, reports, logs, or any data whose meaning is text rather than bytes. Read Text Input, Output, and Encoding for line semantics, UTF-8/16/32, byte order and BOM handling, encoding errors, and the difference between configured and effective encoding.
Standard Streams
Standard input, output, and error connect a command-line application to its surrounding process.
The API provides stable stdIn(), stdOut(), and stdErr() proxies plus concise io formatting helpers.
Use these streams for interactive input, normal program output, diagnostics, and tests that temporarily capture or provide process I/O. Read Standard Streams before redirecting them: redirects are scoped but process-wide, and standard proxies have different ownership rules from ordinary files.
Readiness and Timeouts
Bounded operations let an application remain responsive when a source is slow or a destination cannot immediately accept work. A timeout is a normal result, not end-of-stream and not a failed stream; readiness checks help decide whether retrying can make progress.
Use this part of the API for pipes, terminals, concurrent producers, event-style loops, and any workflow that must
periodically regain control.
Read Readiness and Timeouts for complete input and output retry loops and the exact roles of isReady() and
waitForReady().
Buffering and Back Pressure
Buffering smooths the difference between the size and timing of application requests and native I/O. For output, accepted data may still be queued; back pressure prevents an application from growing that queue without a limit.
Configure this area when moving large data, choosing bounded chunk sizes, controlling memory use, or coordinating
multiple producers.
Read Buffering and Back Pressure to understand front and back buffers, oversized requests, readiness, and when a
successful flush() matters.
Stream Lifecycle
Streams move through Open, Closing, Closed, and Failed states.
Writes, flushing, graceful close, immediate abort, and destruction each make a different guarantee about queued work.
You need these contracts whenever output must not be lost, shutdown can time out, or a stored native failure must be reported reliably. Read Stream Lifecycle for close loops, failure propagation, abort behavior, and deterministic resource release.
Temporary Streams
Temporary streams create a uniquely named byte or text file and combine its stream with an explicit cleanup policy. They are useful for staging an export, materializing intermediate data for another tool, or producing a file that should disappear unless ownership is deliberately transferred.
Read Temporary Streams to configure location, names, access, encoding, and removal; retrieve the path; use
release(); and understand cleanup after close, abort, destruction, or failure.
Positioning Streams
Positioning provides random access to streams whose backing target can support it. Positions are logical encoded-byte offsets, so buffered read-ahead and queued writes do not change the position visible to the caller.
Use positioning for fixed-size records, trailers, indexes, sparse output, or carefully designed random access in encoded text. Read Positioning Streams before seeking: not every stream supports it, append output is excluded, and text boundaries, BOMs, retained input, and timeout behavior require deliberate handling.
Stream Errors and Diagnostics
The API keeps timeout, normal end-of-stream, encoding failure, and stream failure separate so recovery code does not
confuse ordinary flow control with broken I/O.
When a stream does fail, StreamError carries a structured diagnostic with
operation, path, help, and native platform context.
Use Stream Errors and Diagnostics when designing logging, user-facing reports, recovery boundaries, or wrapped streams that must preserve the original source context.
Coroutine Streams
Coroutine operations execute blocking stream work through the worker service without changing the familiar read and
write result states.
Eager CoTask objects handle one operation, while lazy generators yield successive
blocks or lines, including timeout results.
Use them when a coroutine-based component must await I/O or consume a stream incrementally without occupying the caller thread. Read Coroutine Streams for shared ownership across suspension, generator completion, cancellation by destruction, single-consumer rules, and continuation-thread expectations.
Writing Custom Streams
Custom streams connect the common API to an application-specific source or target: an archive entry, protocol channel, device, generated data set, or test double. The base classes supply higher-level behavior only when the implementation obeys the bounded-read, atomic-write, lifecycle, readiness, failure, and optional-positioning contracts.
Use Writing Custom Streams when no built-in stream represents your boundary. It develops complete custom byte input and output streams, explains error context and coroutine ownership, and finishes with a contract-testing checklist.