Як читати зі стандартного рядка вводу за рядком?


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

Відповіді:


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
метод readLine з Predef був застарілий з 2.11.0, тепер рекомендується використовувати метод уscala.io.StdIn
nicolastrres

1
@itemState моя програма не закінчується, якщо я використовую, "io.Source.stdin.getLines" буде очікувати в режимі очікування ... як це зробити ...
Раджа

53

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

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

Якщо ви передаєте файл для генерації вхідних даних, можливо, вам доведеться зупинитися на null або empty, використовуючи:

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

Я знаю про Console.readLine (), я шукаю даний рецепт. Шкала "читання" рядка за рядком із стандартного вводу.
Андрій Чобану,

11
Думаю, ви маєте на увазіtakeWhile(_ != null)
Сет Тісуе

1
Залежить від того, як ви хочете зупинитися. Шукати порожній рядок часто є найпростішим рішенням.
Landei

4
Зверніть увагу, що з Scala 2.11.0 Console.readLineзастаріла, використовуйте StdIn.readlineзамість цього.
Бартломей Салах

Або .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

Здається, це не працює з Scala 2.12.4, або я не знайшов потрібних речей для імпорту.
akauppi

Це працює в Scala 2.12, просто collectметод змінюється так само, як відповідь, тому вам потрібно просто зателефонувати, 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 
...

Доступно тут: API Scaladoc


це не еквівалентно представленому коду з циклом
techkuz

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.