如何从标准输入逐行读取?


91

从标准输入逐行读取的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());
        }
    }
}

Answers:


130

最直接的方法就是使用readLine()的一部分Predef。但是,这很丑陋,因为您需要检查最终的空值:

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

这太冗长了,您宁可使用它java.util.Scanner

我认为将使用更漂亮的方法scala.io.Source

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

3
Predef的readLine方法从2.11.0开始不推荐使用,现在建议在scala.io.StdIn
nicolastrres中

1
@itemState我的程序没有结束,如果我使用“ io.Source.stdin.getLines”将进入等待模式……该如何处理……
Raja

53

对于控制台,您可以使用Console.readLine。您可以写(如果要在空行上停止):

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

如果为文件生成目录以生成输入,则可能需要使用以下命令将其停止为null或为空:

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

我知道Console.readLine(),正在寻找给定的配方。从标准输入逐行读取的“标量”方式。
Andrei Ciobanu

11
我想你是说takeWhile(_ != null)
Seth Tisue 2011年

1
取决于您要如何停止。寻找空行通常是最简单的解决方案。
兰代2011年

4
请注意,Console.readLine不推荐使用Scala 2.11.0 StdIn.readline
巴特洛梅耶Szałach

或者.takeWhile(Option(_).nonEmpty),如果您想null完全避免使用关键字,可能会感觉更好。
康尼

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

6
io.Source.stdin被定义(在scala.io.Source类中),def stdin = fromInputStream(System.in)因此最好坚持使用io.Source.stdin
Nader Ghanbari 2014年

这似乎不适用于Scala 2.12.4,或者我没有找到合适的导入对象。
akauppi,

它工作在斯卡拉2.12,刚才说的collect方法sicne这个答案改变,所以你必须只需要调用input.getLines它给你的Iterator。您可以强制使用.toStream.toList实现它,具体取决于用例。
Nader Ghanbari

11

递归版本(编译器检测到尾递归以提高堆使用率),

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

注意io.StdIn从Scala 2.11开始的使用。还要注意,使用这种方法,我们可以将用户输入累积在最终返回的集合中-除了打印出来。即

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

10

你不能使用

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

如此处可用:Scaladoc API


这不等同于带有循环的演示代码
techkuz

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.