¿Cómo leer desde la entrada estándar línea por línea?

4 minutos de lectura

avatar de usuario
Andrei Ciobanu

¿Cuál es la receta de Scala para leer línea por línea de la entrada estándar? Algo así como el código java equivalente:

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

avatar de usuario
estado del elemento

El enfoque más directo simplemente usará readLine() que es parte de Predef. sin embargo, eso es bastante feo, ya que debe verificar el valor nulo eventual:

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

esto es tan detallado, preferirías usar java.util.Scanner en cambio.

Creo que se usará un enfoque más bonito scala.io.Source:

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

  • el método readLine de Predef quedó en desuso desde 2.11.0, ahora se recomienda usar el método en scala.io.StdIn

    – nicolastres

    8 jun 2018 a las 18:59

  • @itemState mi programa no está finalizando, si uso, “io.Source.stdin.getLines” yendo al modo de espera… ¿cómo manejar esto…

    – Raja

    12 de agosto de 2019 a las 15:15


avatar de usuario
Landéi

Para la consola puedes usar Console.readLine. Puede escribir (si desea detenerse en una línea vacía):

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

Si selecciona un archivo para generar la entrada, es posible que deba detenerse en nulo o vacío usando:

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

  • Conozco Console.readLine(), estoy buscando una receta dada. La forma “Scala” de leer línea por línea desde la entrada estándar.

    – Andréi Ciobanu

    3 de enero de 2011 a las 15:28

  • Creo que quieres decir takeWhile(_ != null)

    – Seth Tejido

    04/01/2011 a las 17:31


  • Depende de cómo quieras parar. Buscar una línea vacía suele ser la solución más sencilla.

    – Landei

    04/01/2011 a las 19:57

  • Tenga en cuenta que desde Scala 2.11.0 Console.readLine está en desuso, use StdIn.readline en cambio.

    – Bartłomiej Szałach

    11/11/2016 a las 11:40

  • O .takeWhile(Option(_).nonEmpty) podría sentirse mejor en caso de que quiera evitar el null palabra clave por completo.

    – conny

    28 de mayo de 2018 a las 11:43

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

  • io.Source.stdin se define (en scala.io.Source clase) como def stdin = fromInputStream(System.in) así que probablemente sea mejor seguir con el io.Source.stdin.

    – Nader Ganbari

    26/10/2014 a las 15:38


  • Esto no parece funcionar con Scala 2.12.4, o no encontré las cosas correctas para importar.

    – akauppi

    19 de febrero de 2018 a las 13:46


  • Funciona en Scala 2.12, solo que el collect el método se cambia desde esta respuesta, por lo que solo tiene que llamar input.getLines lo que te da un Iterator. Puedes forzarlo a materializarse usando .toStream o .toList en él, depende del caso de uso.

    – Nader Ganbari

    06/11/2018 a las 20:33


avatar de usuario
olmo

Una versión recursiva (el compilador detecta una recursividad final para mejorar el uso del almacenamiento dinámico),

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

Nótese el uso de io.StdIn de Scala 2.11. También tenga en cuenta que con este enfoque podemos acumular la entrada del usuario en una colección que finalmente se devuelve, además de imprimirse. A saber,

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

no puedes usar

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

Como disponible aquí: API Scaladoc

  • esto no es equivalente al código presentado con loop

    – Techkuz

    23 de septiembre de 2019 a las 2:56

avatar de usuario
Brad Salomón

Como se señaló brevemente en otros comentarios, scala.Predef.readLine() es obsoleto desde Scala 2.11.0, y puede reemplazarlo con 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 != "")

  • esto no es equivalente al código presentado con loop

    – Techkuz

    23 de septiembre de 2019 a las 2:56

¿Ha sido útil esta solución?