Làm thế nào để đọc từ đầu vào tiêu chuẩn từng dòng?


91

Công thức Scala để đọc từng dòng từ đầu vào chuẩn là gì? Một cái gì đó giống như mã java tương đương:

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

Câu trả lời:


130

Cách tiếp cận nhìn thẳng nhất sẽ chỉ sử dụng readLine()một phần của Predef. tuy nhiên điều đó khá tệ vì bạn cần kiểm tra giá trị null cuối cùng:

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

điều này quá dài dòng, bạn muốn sử dụng java.util.Scannerthay thế.

Tôi nghĩ rằng một cách tiếp cận đẹp hơn sẽ sử dụng scala.io.Source:

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

3
phương pháp Readline của Predef đã bị phản đối từ 2.11.0, bây giờ nó khuyến khích sử dụng phương pháp này trongscala.io.StdIn
nicolastrres

1
@itemState chương trình của tôi không kết thúc, nếu tôi sử dụng, "io.Source.stdin.getLines" sẽ chuyển sang chế độ chờ ... làm thế nào để xử lý điều này ...
Raja

53

Đối với bảng điều khiển bạn có thể sử dụng Console.readLine. Bạn có thể viết (nếu bạn muốn dừng ở một dòng trống):

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

Nếu bạn tạo tệp để tạo dữ liệu đầu vào, bạn có thể phải dừng lại ở giá trị rỗng hoặc trống bằng cách sử dụng:

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

Tôi biết về Console.readLine (), tôi đang tìm kiếm một công thức nhất định. Cách "scala" để đọc từng dòng từ đầu vào Chuẩn.
Andrei Ciobanu

11
Tôi nghĩ rằng bạn có ý nghĩatakeWhile(_ != null)
Seth Tisue

1
Phụ thuộc vào cách bạn muốn dừng lại. Tìm kiếm một dòng trống thường là giải pháp đơn giản nhất.
Landei

4
Lưu ý rằng từ Scala 2.11.0 Console.readLinekhông được dùng nữa, hãy sử dụng StdIn.readlinethay thế.
Bartłomiej Szałach

Hoặc .takeWhile(Option(_).nonEmpty)có thể cảm thấy tốt hơn trong trường hợp bạn muốn tránh nulltừ khóa hoàn toàn.
conny

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

6
io.Source.stdinđược định nghĩa (trong scala.io.Sourcelớp) vì def stdin = fromInputStream(System.in)vậy có lẽ tốt hơn nên gắn bó với io.Source.stdin.
Nader Ghanbari

Điều này dường như không hoạt động với Scala 2.12.4 hoặc tôi không tìm thấy những thứ phù hợp để nhập.
akauppi 19/02/18

Nó hoạt động trong Scala 2.12, chỉ là collectphương pháp được thay đổi nên câu trả lời này nên bạn chỉ cần gọi input.getLinesnó cho bạn một Iterator. Bạn có thể buộc nó thành hiện thực bằng cách sử dụng .toStreamhoặc .toListvào nó, tùy thuộc vào trường hợp sử dụng.
Nader Ghanbari,

11

Một phiên bản đệ quy (trình biên dịch phát hiện đệ quy đuôi để cải thiện việc sử dụng heap),

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

Lưu ý việc sử dụng io.StdIntừ Scala 2.11. Cũng lưu ý rằng với cách tiếp cận này, chúng tôi có thể tích lũy thông tin đầu vào của người dùng trong một bộ sưu tập cuối cùng được trả lại - ngoài việc được in ra. Cụ thể,

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

Bạn có thể không sử dụng

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

Như có sẵn tại đây: API Scaladoc


đây là không tương đương với mã trình bày với loop
techkuz

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.