在Scala中,从InputStream读取到byte数组的最佳方法是什么?
我看到你可以将InputStream转换为char数组。
Source.fromInputStream(is).toArray()
在Scala中,从InputStream读取到byte数组的最佳方法是什么?
我看到你可以将InputStream转换为char数组。
Source.fromInputStream(is).toArray()
怎么样:
Stream.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
更新:使用LazyList代替Stream
(因为在Scala 3中已经弃用了Stream
)
LazyList.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
刚刚通过替换,我们的服务器代码中的瓶颈被移除了
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()
map(_.toByte)
这样逐字节迭代输入... 如果你正在处理大数据,那么就要这样做! - dividebyzero与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
包中了。 - Thiloscala.reflect.io.Streamable.bytes
- WestCoastProjects使用 Scala IO 库,这应该能够工作:
def inputStreamToByteArray(is: InputStream): Array[Byte] =
Resource.fromInputStream(in).byteArray
is.bytes
。better.files
应该只在标准库中存在,它更好用。另外,如果你想要 Array[Byte]
,你需要使用 is.byteArray
。 - Julian PielesSource.fromInputStream(is).map(_.toByte).toArray
如何使用流以及ByteArrayOutputStream的缓冲版本,以最小化围绕最终数组增长的样板文件?
Original Answer翻译成"最初的回答"
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
}
is.readAllBytes()
。
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)
takeWhile
和map
似乎将迭代器转换为迭代器。例如,在 Scala 2.9.3 REPL 中评估Array(1, 2, 3, 4, -1).iterator.takeWhile(-1 !=).map(_.toByte)
将给出Iterator[Byte] = non-empty iterator
。 - mikhail_b