How to read from standard input line by line?

77,212

Solution 1

The most straight-forward looking approach will just use readLine() which is part of Predef. however that is rather ugly as you need to check for eventual null value:

object ScannerTest {
  def main(args: Array[String]) {
    var ok = true
    while (ok) {
      val ln = readLine()
      ok = ln != null
      if (ok) println(ln)
    }
  }
}

this is so verbose, you'd rather use java.util.Scanner instead.

I think a more pretty approach will use scala.io.Source:

object ScannerTest {
  def main(args: Array[String]) {
    for (ln <- io.Source.stdin.getLines) println(ln)
  }
}

Solution 2

For the console you can use Console.readLine. You can write (if you want to stop on an empty line):

Iterator.continually(Console.readLine).takeWhile(_.nonEmpty).foreach(line => println("read " + line))

If you cat a file to generate the input you may need to stop on either null or empty using:

@inline def defined(line: String) = {
  line != null && line.nonEmpty
}
Iterator.continually(Console.readLine).takeWhile(defined(_)).foreach(line => println("read " + line))

Solution 3

val input = Source.fromInputStream(System.in);
val lines = input.getLines.collect

Solution 4

A recursive version (the compiler detects a tail recursion for improved heap usage),

def read: Unit = {
  val s = scala.io.StdIn.readLine()
  println(s)
  if (s.isEmpty) () else read 
}

Note the use of io.StdIn from Scala 2.11 . Also note with this approach we can accumulate user input in a collection that is eventually returned -- in addition to be printed out. Namely,

import annotation.tailrec

def read: Seq[String]= {

  @tailrec
  def reread(xs: Seq[String]): Seq[String] = {
    val s = StdIn.readLine()
    println(s)
    if (s.isEmpty()) xs else reread(s +: xs) 
  }

  reread(Seq[String]())
}

Solution 5

Can you not use

var userinput = readInt // for integers
var userinput = readLine 
...

As available here : Scaladoc API

Share:
77,212
Andrei Ciobanu
Author by

Andrei Ciobanu

Young padawan.

Updated on March 30, 2020

Comments

  • Andrei Ciobanu
    Andrei Ciobanu about 4 years

    What's the Scala recipe for reading line by line from the standard input ? Something like the equivalent java code :

    import java.util.Scanner; 
    
    public class ScannerTest {
        public static void main(String args[]) {
            Scanner sc = new Scanner(System.in);
            while(sc.hasNext()){
                System.out.println(sc.nextLine());
            }
        }
    }
    
  • Andrei Ciobanu
    Andrei Ciobanu over 13 years
    I know about Console.readLine(), I am looking for a given recipe . The "scala" way for reading line by line from Standard input .
  • Seth Tisue
    Seth Tisue over 13 years
    I think you mean takeWhile(_ != null)
  • Landei
    Landei over 13 years
    Depends how you want to stop. Looking for an empty line is often the simplest solution.
  • Nader Ghanbari
    Nader Ghanbari over 9 years
    io.Source.stdin is defined (in scala.io.Source class) as def stdin = fromInputStream(System.in) so probably it's better to stick with the io.Source.stdin.
  • Bartłomiej Szałach
    Bartłomiej Szałach over 7 years
    Note that from Scala 2.11.0 Console.readLine is deprecated, use StdIn.readline instead.
  • akauppi
    akauppi about 6 years
    This doesn't seem to work with Scala 2.12.4, or I didn't find the right things to import.
  • conny
    conny almost 6 years
    Or .takeWhile(Option(_).nonEmpty) might feel better in case you want to avoid the null keyword completely.
  • nicolastrres
    nicolastrres almost 6 years
    the method readLine of Predef was deprecated since 2.11.0, now it's recommended to use the method in scala.io.StdIn
  • Nader Ghanbari
    Nader Ghanbari over 5 years
    It works in Scala 2.12, just that the collect method is changed sicne this answer so you have to just call input.getLines which gives you an Iterator. You can force it to materialize using .toStream or .toList on it, depends on the use case.
  • Raja
    Raja over 4 years
    @itemState my program is not ending, if i use, "io.Source.stdin.getLines" going to wait mode ... how do handle this...
  • techkuz
    techkuz over 4 years
    this is not equivalent to the presented code with loop