Scala: InputStream to Array [Byte] - PullRequest
       38

Scala: InputStream to Array [Byte]

37 голосов
/ 05 февраля 2011

С Scala, как лучше всего читать из InputStream в байтовый массив?

Я вижу, что вы можете преобразовать InputStream в массив char

Source.fromInputStream(is).toArray()

Ответы [ 11 ]

44 голосов
/ 05 февраля 2011

Как насчет:

Stream.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
37 голосов
/ 18 января 2013

Только что удалось устранить узкое место в коде нашего сервера, заменив

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

на

org.apache.commons.io.IOUtils.toByteArray(request.getInputStream)
18 голосов
/ 05 февраля 2011

В том же духе, что и ответ Иццуна ... Я начал это как комментарий, но в итоге он стал слишком длинным!

Я бы предостерег от использования Stream, если удерживать ссылку на элемент head, то потоки могут легко потреблять много памяти.

Учитывая, что вы собираетесь читать файл только один раз, тогда Iterator гораздо лучший выбор:

def inputStreamToByteArray(is: InputStream): Array[Byte] =
  Iterator continually is.read takeWhile (-1 !=) map (_.toByte) toArray
12 голосов
/ 05 февраля 2011
import scala.tools.nsc.io.Streamable
Streamable.bytes(is)

Не помню, как это недавно: вероятно, измеряется в днях. Возвращаясь к 2.8, это больше похоже на

new Streamable.Bytes { def inputStream() = is } toByteArray
10 голосов
/ 02 марта 2011

С Scala IO , это должно работать:

def inputStreamToByteArray(is: InputStream): Array[Byte] = 
   Resource.fromInputStream(in).byteArray
4 голосов
/ 09 марта 2016

С лучше-файлами , вы можете просто сделать is.bytes

3 голосов
/ 11 мая 2014

Source.fromInputStream (есть) .map (_. ToByte) .toArray

1 голос
/ 11 февраля 2019

Как насчет буферизованной версии решения, основанной на потоках, плюс ByteArraOutputStream, чтобы свести к минимуму примерный план по окончательному росту массива?

val EOF: Int = -1

def readBytes(is: InputStream, bufferSize: Int): Array[Byte] = {
  val buf = Array.ofDim[Byte](bufferSize)
  val out = new ByteArrayOutputStream(bufferSize)

  Stream.continually(is.read(buf)) takeWhile { _ != EOF } foreach { n =>
    out.write(buf, 0, n)
  }

  out.toByteArray
}
1 голос
/ 31 августа 2015

Вот подход с использованием 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 голосов
/ 21 января 2019

Альтернатива, основанная на Scala 2.13 новом Seq::unfold:

Seq.unfold(())(_ => Some(is.read.toByte, ()).filter(_._1 != -1)).toArray

и его варианте с использованием сопоставления с образцом:

Seq.unfold(())(_ => is.read.toByte match { case -1 => None case b => Some(b, ()) }).toArray
...