【发布时间】:2011-06-21 18:45:12
【问题描述】:
对于 Scala,从 InputStream 读取到字节数组的最佳方法是什么?
我可以看到您可以将 InputStream 转换为 char 数组
Source.fromInputStream(is).toArray()
【问题讨论】:
标签: scala bytearray inputstream
对于 Scala,从 InputStream 读取到字节数组的最佳方法是什么?
我可以看到您可以将 InputStream 转换为 char 数组
Source.fromInputStream(is).toArray()
【问题讨论】:
标签: scala bytearray inputstream
怎么样:
Stream.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
更新:使用 LazyList 代替 Stream(因为 Stream 在 Scala 3 中已弃用)
LazyList.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
【讨论】:
takeWhile 和 map 似乎将迭代器转换为迭代器。例如。在 Scala 2.9.3 REPL 中评估 Array(1, 2, 3, 4, -1).iterator.takeWhile(-1 !=).map(_.toByte) 给我 Iterator[Byte] = non-empty iterator。
刚刚通过替换消除了我们服务器代码中的瓶颈
Stream.continually(request.getInputStream.read()).takeWhile(_ != -1).map(_.toByte).toArray
与
org.apache.commons.io.IOUtils.toByteArray(request.getInputStream)
或者在纯 Scala 中:
def bytes(in: InputStream, initSize: Int = 8192): Array[Byte] = {
var buf = new Array[Byte](initSize)
val step = initSize
var pos, n = 0
while ({
if (pos + step > buf.length) buf = util.Arrays.copyOf(buf, buf.length << 1)
n = in.read(buf, pos, step)
n != -1
}) pos += n
if (pos != buf.length) buf = util.Arrays.copyOf(buf, pos)
buf
}
在任何情况下都不要忘记关闭打开的输入流:
val in = request.getInputStream
try bytes(in) finally in.close()
【讨论】:
toByteArray 大大加快了速度。
map(_.toByte) 这样的东西逐字节迭代输入......你正在做这个吗大数据!
与 Eastsun 的回答类似...我一开始是评论,但最终变得有点长!
我建议不要使用Stream,如果持有对头元素的引用,那么流很容易消耗大量内存。
鉴于您只会在文件中读取一次,那么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.reflect.io 包。
scala.reflect.io.Streamable.bytes
使用Scala IO,这应该可以:
def inputStreamToByteArray(is: InputStream): Array[Byte] =
Resource.fromInputStream(in).byteArray
【讨论】:
使用better-files,您可以简单地使用is.bytes
【讨论】:
Array[Byte],则需要使用is.byteArray。
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)
【讨论】:
我们可以使用 Google API ByteStreams
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
}
【讨论】: