txt texto sobreescribir por modificar linea leer guardar escribir datos como archivos archivo java scala integration inputstream outputstream

java - texto - ¿Cómo puedo leer un archivo en un InputStream y luego escribirlo en un OutputStream en Scala?



modificar archivos txt en java (5)

Las declaraciones de asignación siempre devuelven la Unidad en Scala, por lo que read = input.read devuelve la Unidad, que nunca es igual a -1. Puedes hacerlo así:

while ({read = input.read; read != -1}) { output.write(read) }

Estoy tratando de usar el código Java básico en Scala para leer un archivo y escribir en un OutputStream , pero cuando uso el tiempo usual (! = -1) en Scala, aparece una advertencia: ¡comparando tipos de Unit y Int con! = siempre cederá verdadero ".

El código es el siguiente:

val file = this.cache.get(imageFileEntry).getValue().asInstanceOf[File] response.setContentType( "image/%s".format( imageDescription.getFormat() ) ) val input = new BufferedInputStream( new FileInputStream( file ) ) val output = response.getOutputStream() var read : Int = -1 while ( ( read = input.read ) != -1 ) { output.write( read ) } input.close() output.flush()

¿Cómo se supone que debo escribir desde un flujo de entrada a un flujo de salida en Scala?

Estoy más interesado en una solución similar a Scala .


Podemos copiar un flujo de entrada a un flujo de salida de una manera genérica y de tipo seguro utilizando tipos de texto. Una clase de tipos es un concepto. Es una aproximación al polimorfismo. En particular, se trata de un polimorfismo paramétrico porque el comportamiento polimórfico se codifica utilizando parámetros. En nuestro caso, nuestros parámetros serán tipos genéricos para los rasgos de Scala.

Hagamos los rasgos Reader[I] y Writer[O] , donde I y O son tipos de flujo de entrada y salida, respectivamente.

trait Reader[I] { def read(input: I, buffer: Array[Byte]): Int } trait Writer[O] { def write(output: O, buffer: Array[Byte], startAt: Int, nBytesToWrite: Int): Unit }

Ahora podemos hacer un método de copia genérico que puede operar en cosas que se suscriben a estas interfaces.

object CopyStreams { type Bytes = Int def apply[I, O](input: I, output: O, chunkSize: Bytes = 1024)(implicit r: Reader[I], w: Writer[O]): Unit = { val buffer = Array.ofDim[Byte](chunkSize) var count = -1 while ({count = r.read(input, buffer); count > 0}) w.write(output, buffer, 0, count) } }

Tenga en cuenta los parámetros r y w implícitos aquí. Básicamente, estamos diciendo que CopyStreams[I,O].apply funcionará si hay un Reader[I] y un Writer[O] en el alcance. Esto nos permitirá llamar a CopyStreams (entrada, salida) sin problemas.

Es importante destacar, sin embargo, que esta implementación es genérica. Funciona en tipos que son independientes de las implementaciones de flujos reales.

En mi caso de uso particular, necesitaba copiar objetos S3 a archivos locales. Así que hice los siguientes valores implícitos.

object Reader { implicit val s3ObjectISReader = new Reader[S3ObjectInputStream] { @inline override def read(input: S3ObjectInputStream, buffer: Array[Byte]): Int = input.read(buffer) } } object Writer { implicit val fileOSWriter = new Writer[FileOutputStream] { @inline override def write(output: FileOutputStream, buffer: Array[Byte], startAt: Int, nBytesToWrite: Int): Unit = output.write(buffer, startAt, nBytesToWrite) } }

Así que ahora puedo hacer lo siguiente:

val input:S3ObjectStream = ... val output = new FileOutputStream(new File(...)) import Reader._ import Writer._ CopyStreams(input, output) // close and such...

Y si alguna vez necesitamos copiar diferentes tipos de flujo, solo necesitamos escribir un nuevo valor implícito de Reader o Writer . Podemos usar el código de CopyStreams sin cambiarlo!


Podrías hacer esto:

Iterator .continually (input.read) .takeWhile (-1 !=) .foreach (output.write)


Si esto es lento:

Iterator .continually (input.read) .takeWhile (-1 !=) .foreach (output.write)

puedes ampliarlo:

val bytes = new Array[Byte](1024) //1024 bytes - Buffer size Iterator .continually (input.read(bytes)) .takeWhile (-1 !=) .foreach (read=>output.write(bytes,0,read)) output.close()


def stream(inputStream: InputStream, outputStream: OutputStream) = { val buffer = new Array[Byte](16384) def doStream(total: Int = 0): Int = { val n = inputStream.read(buffer) if (n == -1) total else { outputStream.write(buffer, 0, n) doStream(total + n) } } doStream() }