How do I read a file line by line in EK9?

← File I/O · Ref: Q154

EK9 treats file input as a stream source. Open a file with TextFile.input() inside a try block, then use cat to pipe lines through stream operations like filter, map, and collect.

STREAMING FILE INPUT

Open the file and stream its contents:

  file <- TextFile("data.txt")
  try
    -> input <- file.input()
    cat input > stdout

Each line from the file flows through the pipeline as a String.

CAT WITH FILE INPUT

The cat operation treats the input stream as a source of lines:

  cat input | map with processLine > stdout

This sends each line through the processLine function before printing.

FILTER AND TRANSFORM LINES

Combine file streaming with pipeline operations:

  cat input | filter by notEmpty | map with trim > stdout

This skips empty lines and trims whitespace from each remaining line.

COLLECT LINES INTO LIST

Gather all lines into a collection:

  cat input | collect as List of String

This reads every line and stores them in a List for further processing.

See Q89 for stream pipelines. See Q151 for reading files. See Q125 for head/tail/skip.

Example

defines module qa.fileio.lines

  defines function

    notEmpty() as pure
      -> line as String
      <- rtn as Boolean: line?

    addLineNumber() as pure
      -> line as String
      <- rtn as String: ">> " + line

  defines program

    ReadFileLinesDemo()
      stdout <- Stdout()

      // === TEXTFILE FOR LINE READING ===

      file <- TextFile("/tmp/qa-example-lines.txt")
      stdout.println("File for line reading: " + $file)

      // === STREAMING PATTERN ===

      // The standard pattern for line-by-line processing:
      //   try
      //     -> input <- file.input()
      //     cat input | filter by notEmpty | map with addLineNumber > stdout

      // === FILTER AND TRANSFORM ===

      // Stream operations work naturally with file input:
      //   cat input | filter by notEmpty | head 10 > stdout

      // === COLLECT INTO LIST ===

      // Gather lines into a collection:
      //   cat input | collect as List of String

      stdout.println("Line-by-line processing uses cat with file input streams")

Common mistakes

E50060 — TextFile has no toString() method. Use the $ prefix operator for string conversion. See ek9 -h E50060 for details.

Incorrect:

stdout.println(file.toString())

Correct:

stdout.println("File for line reading: " + $file)

E50060 — TextFile has no readLines() method. Use file.input() inside a try block to get a stream for line-by-line processing. See ek9 -h E50060 for details.

Incorrect:

stdout.println(file.readLines())

Correct:

stdout.println("Line-by-line processing uses cat with file input streams")
Other ways to ask this
  • How do I process a file line by line in EK9?
  • How do I stream file contents in EK9?
  • How do I use cat with file input in EK9?

Coming from another language?

Java: Files.lines(Path) returns a Stream of String for lazy line-by-line processing. Python: for line in open('file') iterates lazily. Rust: BufRead::lines() returns an iterator of lines. Go: bufio.Scanner for line-by-line reading. EK9: cat input with TextFile.input() in a stream pipeline, supporting filter, map, collect and all stream operations.

Keywords: line, cat, read, filter, lines, iterate, stream, file, write, pipeline