2011-02-05 18 views

Odpowiedz

37

Jak o:

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

Czy mógłbyś wyjaśnić różnicę między tym a wariantem pytania? – Jus12

+0

@ Jus12 Szukałem tablicy bajtów. To, co mam w pytaniu, to sposób na uzyskanie tablicy znaków. – rahul

+11

Czy nie utworzy to ogromnie połączonej listy, a następnie przekształci ją w tablicę? To nie wygląda zbyt efektywnie, w czasie ani w pamięci. –

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

Czy lista [Bajtów] ma metodę "dodaj"? – Eastsun

+0

Dobre pytanie. Po prostu zmieniłem go, aby używał zmiennego ListBuffer –

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

nie pamiętam jak niedawno, że jest: prawdopodobnie mierzony w dniach. Wracając do 2,8, to nic więcej jak

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

Czy można bezpiecznie używać rzeczy z pakietów scala.tools? Czy są one nawet częścią standardowej biblioteki? –

+0

Nie. Ale jeśli chcesz wiedzieć, jak to napisać, to jest. – extempore

+1

Wygląda na to, że przeniosło się teraz do bardziej standardowego pakietu 'scala.reflect.io'. – Thilo

17

W podobnym duchu, aby odpowiedzieć Eastsun za ... Zacząłem to jako komentarz, ale skończyło się tylko trochę za długo!

Ostrzegam przed używaniem Stream, jeśli przechowujemy odniesienie do elementu głównego, strumienie mogą łatwo zużywać dużo pamięci.

Biorąc pod uwagę, że jesteś tylko będzie czytać w pliku raz, potem Iterator jest znacznie lepszym wyborem:

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

Z Scala IO, to powinno działać:

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

Wystarczy usunięty wąskie gardło w naszym kodzie serwera, zamieniając

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

z

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

To jest org.apache.commons.io.IOUtils.toByteArray, na wypadek gdyby ktoś się zastanawiał. – Haakon

+0

@Haakon dziękuję! Zaktualizowałem odpowiedź. –

+0

To zdecydowanie czuje się szybciej. Ktoś zrobił jakieś testy lub testy z większymi plikami? – EdgeCaseBerg

2

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

+2

Ta operacja kończy się niepowodzeniem w przypadku plików tekstowych zakodowanych binarnie/fałszywie: http://stackoverflow.com/questions/13327536/malformedinputexception-when-trying-to-read-entire-file –

1

Oto podejście używając 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

Prawdopodobnie nie ma powodu do obniżenia, to pokonałoby przyrostowy charakter strumienie – OlegYch

+0

Powód jest taki, że pytanie wymaga tablicy bajtów. –