如何逐行读取标准输入?

Scala 从标准输入逐行读取的配方是什么?类似于等价的 java 代码:

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());
}
}
}
77870 次浏览

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))
val input = Source.fromInputStream(System.in);
val lines = input.getLines.collect

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)
}
}

Can you not use

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

As available here : Scaladoc API

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]())
}

As noted briefly in other comments, scala.Predef.readLine() is deprecated since Scala 2.11.0, and you can replace it with scala.io.StdIn.readLine():

// Read STDIN lines until a blank one
import scala.io.StdIn.readLine


var line = ""
do {
line = readLine()
println("Read: " + line)
} while (line != "")