Wie lese ich zeilenweise von der Standardeingabe?

90

Was ist das Scala-Rezept zum zeilenweisen Lesen von der Standardeingabe? So etwas wie der entsprechende Java-Code:

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

Antworten:

130

Der geradlinigste Ansatz wird nur den verwenden, readLine()der Teil von ist Predef. Dies ist jedoch ziemlich hässlich, da Sie nach einem möglichen Nullwert suchen müssen:

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

Dies ist so ausführlich, dass Sie es lieber verwenden java.util.Scannermöchten.

Ich denke, ein hübscherer Ansatz wird verwenden scala.io.Source:

object ScannerTest {
  def main(args: Array[String]) {
    for (ln <- io.Source.stdin.getLines) println(ln)
  }
}
itemState
quelle
3
Die Methode readLine von Predef war seit 2.11.0 veraltet. Jetzt wird empfohlen, die Methode inscala.io.StdIn
nicolastrres
1
@itemState mein Programm endet nicht, wenn ich "io.Source.stdin.getLines" verwende, um zu warten ... wie gehe ich damit um ...
Raja
53

Für die Konsole können Sie verwenden Console.readLine. Sie können schreiben (wenn Sie in einer leeren Zeile anhalten möchten):

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

Wenn Sie eine Datei katzen, um die Eingabe zu generieren, müssen Sie möglicherweise mit null oder leer anhalten, indem Sie:

@inline def defined(line: String) = {
  line != null && line.nonEmpty
}
Iterator.continually(Console.readLine).takeWhile(defined(_)).foreach(line => println("read " + line))
Landei
quelle
Ich kenne Console.readLine () und suche nach einem bestimmten Rezept. Die "Scala" -Methode zum zeilenweisen Lesen von Standardeingaben.
Andrei Ciobanu
11
Ich denke du meinsttakeWhile(_ != null)
Seth Tisue
1
Kommt darauf an, wie du aufhören willst. Die Suche nach einer leeren Zeile ist oft die einfachste Lösung.
Landei
4
Beachten Sie, dass Scala 2.11.0 Console.readLineveraltet ist. Verwenden Sie StdIn.readlinestattdessen.
Bartłomiej Szałach
Oder .takeWhile(Option(_).nonEmpty)fühlen Sie sich besser, wenn Sie das nullSchlüsselwort vollständig vermeiden möchten .
Conny
27
val input = Source.fromInputStream(System.in);
val lines = input.getLines.collect
Jason
quelle
6
io.Source.stdinist definiert (in der scala.io.SourceKlasse) als def stdin = fromInputStream(System.in)so wahrscheinlich ist es besser, bei der zu bleiben io.Source.stdin.
Nader Ghanbari
Dies scheint mit Scala 2.12.4 nicht zu funktionieren, oder ich habe nicht die richtigen Dinge zum Importieren gefunden.
Akauppi
Es funktioniert in Scala 2.12, nur dass die collectMethode in dieser Antwort geändert wird, so dass Sie nur aufrufen müssen input.getLines, was Ihnen eine gibt Iterator. Sie können es zwingen, mit .toStreamoder .toListauf es zu materialisieren , abhängig vom Anwendungsfall.
Nader Ghanbari
11

Eine rekursive Version (der Compiler erkennt eine Endrekursion für eine verbesserte Heap-Nutzung),

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

Beachten Sie die Verwendung io.StdInvon Scala 2.11. Beachten Sie auch, dass wir mit diesem Ansatz Benutzereingaben in einer Sammlung sammeln können, die schließlich zurückgegeben wird - zusätzlich zum Ausdrucken. Nämlich,

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

Kannst du nicht benutzen

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

Wie hier verfügbar: Scaladoc API

Kaning
quelle
Dies ist nicht gleichbedeutend mit dem präsentierten Code mit Schleife
techkuz
0

Wie in anderen Kommentaren kurz erwähnt, scala.Predef.readLine()ist es seit Scala 2.11.0 veraltet und Sie können es ersetzen durch 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 != "")
Brad Solomon
quelle