使用Scala,从InputStream读取到字节数组的最佳方法是什么?
我看到您可以将InputStream转换为char数组
Source.fromInputStream(is).toArray()
怎么样:
Stream.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
我们可以使用google API ByteStreams做到这一点
import com.google.common.io.ByteStreams
将流传递到ByteStreams.toByteArray方法进行转换
ByteStreams.toByteArray(stream)
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
}
基于Scala 2.13
的新Seq::unfold
的替代方法:
Seq::unfold
及其使用模式匹配的变体:
Seq.unfold(())(_ => Some(is.read.toByte, ()).filter(_._1 != -1)).toArray
只需替换掉我们服务器代码中的瓶颈
Stream.continually(request.getInputStream.read()).takeWhile(_ != -1).map(_.toByte).toArray
with
org.apache.commons.io.IOUtils.toByteArray(request.getInputStream)
与Eastsun的回答类似……我以评论开始,但最终变得有点冗长!
我警告不要使用Stream
,如果持有对head元素的引用,则流很容易消耗大量内存。
鉴于您只需要读一次文件,那么Iterator
是更好的选择:
def inputStreamToByteArray(is: InputStream): Array[Byte] =
Iterator continually is.read takeWhile (-1 !=) map (_.toByte) toArray
import scala.tools.nsc.io.Streamable
Streamable.bytes(is)
不记得最近的时间:可能以天为单位。回到2.8,它更像
new Streamable.Bytes { def inputStream() = is } toByteArray
使用Scala IO,这应该可以工作:
def inputStreamToByteArray(is: InputStream): Array[Byte] =
Resource.fromInputStream(in).byteArray
使用better-files,您只需执行is.bytes
Source.fromInputStream(is).map(_。toByte).toArray
基于流加上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
}
这里是使用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)