Bagaimana cara membaca dari baris masukan standar demi baris?


91

Apa resep Scala untuk membaca baris demi baris dari input standar? Sesuatu seperti kode java yang setara:

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

Jawaban:


130

Pendekatan yang paling lurus ke depan hanya akan menggunakan readLine()yang merupakan bagian dari Predef. Namun itu agak jelek karena Anda perlu memeriksa nilai null akhirnya:

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

ini sangat bertele-tele, Anda lebih suka menggunakannya java.util.Scanner.

Saya pikir pendekatan yang lebih cantik akan menggunakan scala.io.Source:

object ScannerTest {
  def main(args: Array[String]) {
    for (ln <- io.Source.stdin.getLines) println(ln)
  }
}

3
metode readLine of Predef tidak digunakan lagi sejak 2.11.0, sekarang disarankan untuk menggunakan metode discala.io.StdIn
nicolastrres

1
@itemState Program saya tidak berakhir, jika saya menggunakan, "io.Source.stdin.getLines" akan menunggu mode ... bagaimana menangani ini ...
Raja

53

Untuk konsol, Anda dapat menggunakan Console.readLine. Anda dapat menulis (jika Anda ingin berhenti di baris kosong):

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

Jika Anda membuat file untuk menghasilkan input, Anda mungkin perlu berhenti pada null atau kosong menggunakan:

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

Saya tahu tentang Console.readLine (), saya mencari resep yang diberikan. Cara "skala" untuk membaca baris demi baris dari input Standar.
Andrei Ciobanu

11
Saya pikir maksud AndatakeWhile(_ != null)
Seth Tisue

1
Tergantung bagaimana Anda ingin berhenti. Mencari baris kosong seringkali merupakan solusi paling sederhana.
Landei

4
Perhatikan bahwa dari Scala 2.11.0 Console.readLinetidak digunakan lagi, gunakan StdIn.readlinesaja.
Bartłomiej Szałach

Atau .takeWhile(Option(_).nonEmpty)mungkin merasa lebih baik jika Anda ingin menghindari nullkata kunci sepenuhnya.
conny

27
val input = Source.fromInputStream(System.in);
val lines = input.getLines.collect

6
io.Source.stdindidefinisikan (di scala.io.Sourcekelas) def stdin = fromInputStream(System.in)jadi mungkin lebih baik untuk tetap menggunakan io.Source.stdin.
Nader Ghanbari

Ini sepertinya tidak berfungsi dengan Scala 2.12.4, atau saya tidak menemukan hal yang tepat untuk diimpor.
akauppi

Ia bekerja di Scala 2.12, hanya saja collectmetodenya diubah sejak jawaban ini sehingga Anda hanya perlu memanggil input.getLinesyang memberi Anda Iterator. Anda dapat memaksanya untuk terwujud menggunakan .toStreamatau .toListdi atasnya, tergantung pada kasus penggunaan.
Nader Ghanbari

11

Versi rekursif (kompilator mendeteksi rekursi ekor untuk peningkatan penggunaan heap),

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

Perhatikan penggunaan io.StdIndari Scala 2.11. Perhatikan juga dengan pendekatan ini, kita dapat mengakumulasikan input pengguna dalam koleksi yang akhirnya dikembalikan - selain untuk dicetak. Yaitu,

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

Bisakah kamu tidak menggunakan

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

Seperti yang tersedia di sini: API Scaladoc


ini tidak sama dengan kode yang disajikan dengan loop
techkuz

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.