如何逐行读取标准输入?

How to read from standard input line by line?

提问人:Andrei Ciobanu 提问时间:1/3/2011 最后编辑:Jacek LaskowskiAndrei Ciobanu 更新时间:3/29/2020 访问量:78339

问:

从标准输入中逐行读取的 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());
        }
    }
}
Java Scala IO java.util.scanner

评论


答:

54赞 Landei 1/3/2011 #1

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

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

如果 cat 文件来生成输入,则可能需要在 null 或空时停止,使用:

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

评论

0赞 Andrei Ciobanu 1/3/2011
我知道 Console.readLine(),我正在寻找给定的食谱。从标准输入中逐行读取的“scala”方式。
11赞 Seth Tisue 1/5/2011
我想你的意思是takeWhile(_ != null)
1赞 Landei 1/5/2011
取决于你想如何停止。寻找空行通常是最简单的解决方案。
6赞 Bartłomiej Szałach 11/11/2016
请注意,从 Scala 2.11.0 开始,已弃用,请改用。Console.readLineStdIn.readline
0赞 conny 5/28/2018
或者,如果您想完全避免使用关键字,可能会感觉更好。.takeWhile(Option(_).nonEmpty)null
27赞 Jason 1/3/2011 #2
val input = Source.fromInputStream(System.in);
val lines = input.getLines.collect

评论

6赞 Nader Ghanbari 10/26/2014
io.Source.stdin被定义(在课堂上),所以最好坚持使用 .scala.io.Sourcedef stdin = fromInputStream(System.in)io.Source.stdin
0赞 akauppi 2/19/2018
这似乎不适用于 Scala 2.12.4,或者我没有找到要导入的正确内容。
0赞 Nader Ghanbari 11/7/2018
它在 Scala 2.12 中有效,只是方法更改了这个答案,所以你只需要调用它给你一个 .您可以强制它使用或基于它来实现,具体取决于用例。collectinput.getLinesIterator.toStream.toList
132赞 itemState 1/3/2011 #3

最直接的方法将只使用其中的一部分。但是,这是相当丑陋的,因为您需要检查最终的 null 值: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)
  }
}

评论

4赞 nicolastrres 6/9/2018
自 2.11.0 起,Predef 的 readLine 方法已被弃用,现在建议在scala.io.StdIn
1赞 Raja 8/12/2019
@itemState我的程序不会结束,如果我使用“io.Source.stdin.getLines“将进入等待模式......如何处理这个问题...
10赞 kaning 12/15/2011 #4

你不能使用

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

此处可用:Scaladoc API

评论

0赞 techkuz 9/23/2019
这并不等同于所呈现的带有循环的代码
12赞 elm 4/14/2016 #5

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

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

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

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]())
}
2赞 Brad Solomon 3/29/2020 #6

正如在其他评论中简要指出的那样,scala.Predef.readLine() Scala 2.11.0 起已弃用,您可以将其替换为 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 != "")