How to read from standard input line by line?
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
Comments
-
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 over 13 yearsI know about Console.readLine(), I am looking for a given recipe . The "scala" way for reading line by line from Standard input .
-
Seth Tisue over 13 yearsI think you mean
takeWhile(_ != null)
-
Landei over 13 yearsDepends how you want to stop. Looking for an empty line is often the simplest solution.
-
Nader Ghanbari over 9 years
io.Source.stdin
is defined (inscala.io.Source
class) asdef stdin = fromInputStream(System.in)
so probably it's better to stick with theio.Source.stdin
. -
Bartłomiej Szałach over 7 yearsNote that from Scala 2.11.0
Console.readLine
is deprecated, useStdIn.readline
instead. -
akauppi about 6 yearsThis doesn't seem to work with Scala 2.12.4, or I didn't find the right things to import.
-
conny almost 6 yearsOr
.takeWhile(Option(_).nonEmpty)
might feel better in case you want to avoid thenull
keyword completely. -
nicolastrres almost 6 yearsthe method readLine of Predef was deprecated since 2.11.0, now it's recommended to use the method in
scala.io.StdIn
-
Nader Ghanbari over 5 yearsIt works in Scala 2.12, just that the
collect
method is changed sicne this answer so you have to just callinput.getLines
which gives you anIterator
. You can force it to materialize using.toStream
or.toList
on it, depends on the use case. -
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 over 4 yearsthis is not equivalent to the presented code with loop