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

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

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))

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

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

10

Kannst du nicht benutzen

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

Wie hier verfügbar: Scaladoc API


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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.