Как читать из стандартного ввода построчно?

Каков рецепт 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());
        }
    }
}

person Andrei Ciobanu    schedule 03.01.2011    source источник


Ответы (6)


Самый прямолинейный подход будет просто использовать 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)
  }
}
person itemState    schedule 03.01.2011
comment
метод readLine из Predef устарел с версии 2.11.0, теперь рекомендуется использовать метод в scala.io.StdIn - person nicolastrres; 08.06.2018
comment
@itemState моя программа не заканчивается, если я использую, io.Source.stdin.getLines переходит в режим ожидания ... как с этим справиться ... - person Raja; 12.08.2019

Для консоли вы можете использовать Console.readLine. Вы можете написать (если хотите остановиться на пустой строке):

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

Если вы запускаете файл для создания ввода, вам может потребоваться остановиться либо на нулевом, либо на пустом, используя:

@inline def defined(line: String) = {
  line != null && line.nonEmpty
}
Iterator.continually(Console.readLine).takeWhile(defined(_)).foreach(line => println("read " + line))
person Landei    schedule 03.01.2011
comment
Я знаю о Console.readLine(), я ищу данный рецепт. Способ scala для построчного чтения из стандартного ввода. - person Andrei Ciobanu; 03.01.2011
comment
Я думаю, вы имеете в виду takeWhile(_ != null) - person Seth Tisue; 04.01.2011
comment
Зависит от того, как вы хотите остановиться. Поиск пустой строки часто является самым простым решением. - person Landei; 04.01.2011
comment
Обратите внимание, что из Scala 2.11.0 Console.readLine устарело, вместо этого используйте StdIn.readline. - person Bartłomiej Szałach; 11.11.2016
comment
Или .takeWhile(Option(_).nonEmpty) может показаться лучше, если вы хотите полностью избежать ключевого слова null. - person conny; 28.05.2018

Рекурсивная версия (компилятор обнаруживает хвостовую рекурсию для улучшения использования кучи),

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]())
}
person elm    schedule 14.04.2016

Ты не можешь использовать

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

Доступно здесь: Scaladoc API

person kaning    schedule 15.12.2011
comment
это не эквивалентно представленному коду с циклом - person techkuz; 23.09.2019

Как кратко отмечено в других комментариях, scala.Predef.readLine() устарел< /a> начиная с 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 != "")
person Brad Solomon    schedule 29.03.2020

person    schedule
comment
io.Source.stdin определяется (в классе scala.io.Source) как def stdin = fromInputStream(System.in), поэтому, вероятно, лучше придерживаться io.Source.stdin. - person Nader Ghanbari; 26.10.2014
comment
Похоже, это не работает со Scala 2.12.4, или я не нашел нужных вещей для импорта. - person akauppi; 19.02.2018
comment
Он работает в Scala 2.12, просто метод collect изменен с учетом этого ответа, поэтому вам нужно просто вызвать input.getLines, что даст вам Iterator. Вы можете заставить его материализоваться, используя .toStream или .toList, в зависимости от варианта использования. - person Nader Ghanbari; 06.11.2018