Comment lire une entrée standard ligne par ligne?


91

Quelle est la recette Scala pour lire ligne par ligne à partir de l'entrée standard? Quelque chose comme le code java équivalent:

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

Réponses:


130

L'approche la plus simple utilisera simplement readLine()ce qui fait partie de Predef. cependant c'est plutôt moche car vous devez vérifier la valeur nulle éventuelle:

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

c'est tellement verbeux que vous préférez utiliser à la java.util.Scannerplace.

Je pense qu'une approche plus jolie utilisera scala.io.Source:

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

3
la méthode readLine de Predef est obsolète depuis la 2.11.0, il est maintenant recommandé d'utiliser la méthode dansscala.io.StdIn
nicolastrres

1
@itemState mon programme ne se termine pas, si j'utilise, "io.Source.stdin.getLines" passe en mode attente ... comment gérer cela ...
Raja

53

Pour la console, vous pouvez utiliser Console.readLine. Vous pouvez écrire (si vous voulez vous arrêter sur une ligne vide):

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

Si vous créez un fichier pour générer l'entrée, vous devrez peut-être vous arrêter sur null ou vide en utilisant:

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

Je connais Console.readLine (), je recherche une recette donnée. La méthode "scala" pour lire ligne par ligne à partir de l'entrée Standard.
Andrei Ciobanu

11
Je pense que vous voulez diretakeWhile(_ != null)
Seth Tisue

1
Cela dépend de la façon dont vous voulez vous arrêter. La recherche d'une ligne vide est souvent la solution la plus simple.
Landei le

4
Notez que de Scala 2.11.0 Console.readLineest obsolète, utilisez à la StdIn.readlineplace.
Bartłomiej Szałach

Ou .takeWhile(Option(_).nonEmpty)vous vous sentirez peut-être mieux au cas où vous voudriez éviter nullcomplètement le mot - clé.
conny

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

6
io.Source.stdinest défini (en scala.io.Sourceclasse) comme il est def stdin = fromInputStream(System.in)donc probablement préférable de s'en tenir au io.Source.stdin.
Nader Ghanbari

Cela ne semble pas fonctionner avec Scala 2.12.4, ou je n'ai pas trouvé les bons éléments à importer.
akauppi

Cela fonctionne dans Scala 2.12, juste que la collectméthode soit modifiée sicne cette réponse donc vous devez simplement appeler input.getLinesce qui vous donne un Iterator. Vous pouvez le forcer à se matérialiser en utilisant .toStreamou .toListdessus, selon le cas d'utilisation.
Nader Ghanbari

11

Une version récursive (le compilateur détecte une récursivité de queue pour une meilleure utilisation du tas),

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

Notez l'utilisation de io.StdInde Scala 2.11. Notez également qu'avec cette approche, nous pouvons accumuler les entrées utilisateur dans une collection qui est finalement retournée - en plus d'être imprimée. À savoir,

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

Ne peux-tu pas utiliser

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

Disponible ici: API Scaladoc


ce n'est pas équivalent au code présenté avec boucle
techkuz

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.