Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Text and Byte Streams

Streams are sequential sources and sinks: you read or write incrementally (a rune, a line, a byte, a chunk) without loading everything at once. The same programming model applies whether the backing store is a file, an in-memory string or buffer, or the process’s stdin/stdout.

Final splits streams along two axes you already saw in the Features survey:

AxisChoices
UnitText (Utf-8 runes / strings / lines) vs bytes (raw octets in a ByteList)
DirectionRead (pull) vs Write (push)

That gives four role types — the shapes APIs ask for:

TypeRole
TextReadread Utf-8 text
TextWritewrite Utf-8 text
ByteReadread raw bytes
ByteWritewrite raw bytes

You usually open a concrete handle with a class factory on TextReader, TextWriter, ByteReader, or ByteWriter (TextReader.newFromFile^, ByteWriter.newFromBytes^, and so on). Those handles implement the matching role. Other types can too — for example StringBuilder is a TextWrite.

Final does not expose a general “open File, then ask it for a stream” workflow for day-to-day I/O — the stream factories are the entry point. (A small File helper exists for checks like fileExists?; see File Streams.)

Already covered elsewhere

  • $ prints to the session’s stdout (Hello Final).
  • ByteList is the compact unsigned 8-bit buffer used with byte streams (Numeric Lists).
  • Pips inherit stdout/stderr; prefer write* on a TextWrite / ByteWrite for real I/O (Pips).

In this section

Use list-streams then help TextRead / help TextReader (and the other type names) in the UI for the full member list and stack effects.