2011-02-05 33 views
31

Con Scala, ¿cuál es la mejor manera de leer desde un InputStream a un bytearray?Scala: InputStream to Array [Byte]

puedo ver que se puede convertir un InputStream a char matriz

Source.fromInputStream(is).toArray() 

Respuesta

37

¿Qué tal:

Stream.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray 
+1

¿Podría explicar la diferencia entre esto y la variante en la pregunta? – Jus12

+0

@ Jus12 Estaba buscando una matriz de bytes. Lo que tengo en la pregunta, es una forma de obtener la matriz de caracteres. – rahul

+11

¿No creará eso una gran lista vinculada y luego la convertirá en una matriz? Eso no parece muy eficiente, en tiempo o memoria. –

0
def inputStreamToByteArray(is: InputStream): Array[Byte] = { 
    val buf = ListBuffer[Byte]() 
    var b = is.read() 
    while (b != -1) { 
     buf.append(b.byteValue) 
     b = is.read() 
    } 
    buf.toArray 
} 
+0

¿Lista [Byte] tiene un método "agregar"? – Eastsun

+0

Buena pregunta. Acabo de editarlo para usar un ListBuffer mutable –

11
import scala.tools.nsc.io.Streamable 
Streamable.bytes(is) 

No recuerdo cómo reciente que es: probablemente mide en días. Volviendo a 2,8, que es más como

new Streamable.Bytes { def inputStream() = is } toByteArray 
+1

¿Es seguro usar cosas de los paquetes scala.tools? ¿Son parte de la biblioteca estándar? –

+0

No. Pero si quieres saber cómo escribirlo, ahí está. – extempore

+1

Parece que se ha movido al paquete 'scala.reflect.io' más estándar ahora. – Thilo

17

En una línea similar a la respuesta de Eastsun ... Empecé esto como un comentario, pero terminó siendo sólo un poco a largo!

Te advierto contra el uso de Stream, si mantiene una referencia al elemento principal, las transmisiones pueden consumir mucha memoria.

Teniendo en cuenta que usted sólo va a leer en el archivo una vez, luego Iterator es una opción mucho mejor:

def inputStreamToByteArray(is: InputStream): Array[Byte] = 
    Iterator continually is.read takeWhile (-1 !=) map (_.toByte) toArray 
10

Con Scala IO, esto debería funcionar:

cuello de botella
def inputStreamToByteArray(is: InputStream): Array[Byte] = 
    Resource.fromInputStream(in).byteArray 
36

Sólo eliminado en nuestro código de servidor al reemplazar

Stream.continually(request.getInputStream.read()).takeWhile(_ != -1).map(_.toByte).toArray 

con

org.apache.commons.io.IOUtils.toByteArray(request.getInputStream) 
+0

Eso es org.apache.commons.io.IOUtils.toByteArray, en caso de que alguien se lo esté preguntando. – Haakon

+0

@Haakon gracias! Actualicé la respuesta. –

+0

Esto definitivamente se siente más rápido. ¿Alguien hizo benchmarks o pruebas con archivos más grandes? – EdgeCaseBerg

2

Source.fromInputStream (es) .map (. _ ToByte) .toArray

+2

Esto falla en los archivos de texto con codificación binaria/falsa: http://stackoverflow.com/questions/13327536/malformedinputexception-when-trying-to-read-entire-file –

1

He aquí un método que utiliza scalaz-stream:

import scalaz.concurrent.Task 
import scalaz.stream._ 
import scodec.bits.ByteVector 

def allBytesR(is: InputStream): Process[Task, ByteVector] = 
    io.chunkR(is).evalMap(_(4096)).reduce(_ ++ _).lastOr(ByteVector.empty) 
+0

probablemente no haya ninguna razón para reducir, eso vencería la naturaleza incremental de streams – OlegYch

+0

La razón es que la pregunta requiere una matriz de bytes. –