Jak czytać ze standardowego wejścia wiersz po wierszu?

91

Jaki jest przepis Scala na czytanie wiersz po wierszu ze standardowego wejścia? Coś w rodzaju równoważnego kodu 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());
        }
    }
}
Andrei Ciobanu
źródło

Odpowiedzi:

130

Najbardziej bezpośrednie podejście będzie po prostu używać tego, readLine()co jest częścią Predef. jest to jednak raczej brzydkie, ponieważ musisz sprawdzić ostateczną wartość null:

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

jest to tak rozwlekłe, że wolisz zamiast java.util.Scannertego użyć .

Myślę, że bardziej ładne podejście będzie używać scala.io.Source:

object ScannerTest {
  def main(args: Array[String]) {
    for (ln <- io.Source.stdin.getLines) println(ln)
  }
}
itemState
źródło
3
metoda readLine z Predef była przestarzała od 2.11.0, teraz zaleca się użycie metody wscala.io.StdIn
nicolastrres
1
@itemState mój program się nie kończy, jeśli użyję „io.Source.stdin.getLines” przechodzę w tryb oczekiwania ... jak sobie z tym poradzić ...
Raja
53

Do konsoli możesz użyć Console.readLine. Możesz napisać (jeśli chcesz zatrzymać się w pustej linii):

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

Jeśli utworzysz plik w celu wygenerowania danych wejściowych, może być konieczne zatrzymanie się na wartości null lub pustej za pomocą:

@inline def defined(line: String) = {
  line != null && line.nonEmpty
}
Iterator.continually(Console.readLine).takeWhile(defined(_)).foreach(line => println("read " + line))
Landei
źródło
Wiem o Console.readLine (), szukam danego przepisu. „Scala” do czytania wiersz po wierszu ze standardowego wejścia.
Andrei Ciobanu,
11
Myślę, że masz na myślitakeWhile(_ != null)
Seth Tisue
1
Zależy, jak chcesz przestać. Poszukiwanie pustej linii jest często najprostszym rozwiązaniem.
Landei
4
Zauważ, że ze Scali 2.11.0 Console.readLinejest przestarzałe, użyj StdIn.readlinezamiast tego.
Bartłomiej Szałach 11.11.16
Lub .takeWhile(Option(_).nonEmpty)może poczuć się lepiej, jeśli chcesz nullcałkowicie uniknąć słowa kluczowego.
conny
27
val input = Source.fromInputStream(System.in);
val lines = input.getLines.collect
Jason
źródło
6
io.Source.stdinjest zdefiniowany (w scala.io.Sourceklasie), def stdin = fromInputStream(System.in)więc prawdopodobnie lepiej jest trzymać się io.Source.stdin.
Nader Ghanbari
Wygląda na to, że nie działa ze Scala 2.12.4 lub nie znalazłem odpowiednich rzeczy do zaimportowania.
akauppi
Działa w Scali 2.12, tylko że collectmetoda została zmieniona, więc musisz po prostu wywołać, input.getLinesco daje ci Iterator. Możesz zmusić go do materializacji za pomocą .toStreamlub .toListna nim, w zależności od przypadku użycia.
Nader Ghanbari
11

Wersja rekurencyjna (kompilator wykrywa rekurencję ogona w celu lepszego wykorzystania sterty),

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

Zwróć uwagę na użycie io.StdInz Scala 2.11. Zauważ również, że dzięki temu podejściu możemy gromadzić dane wejściowe użytkownika w kolekcji, która jest ostatecznie zwracana - oprócz tego, że zostanie wydrukowana. Mianowicie,

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]())
}
wiąz
źródło
10

Nie możesz użyć

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

Dostępne tutaj: Scaladoc API

kaning
źródło
nie jest to odpowiednik przedstawionego kodu z pętlą
techkuz
1

Jak wspomniano pokrótce w innych komentarzach, scala.Predef.readLine()jest przestarzały od wersji Scala 2.11.0 i można go zastąpić 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
źródło