如何将Scala流的内容写入文件?

mro*_*rog 6 io scala

我有一个Scala字节流,我想写入文件.流有太多数据来缓冲所有内存.

作为第一次尝试,我创建了一个InputStream类似的:

class MyInputStream(data: Stream[Byte]) extends InputStream {
  private val iterator = data.iterator
  override def read(): Int = if (iterator.hasNext) iterator.next else -1
}
Run Code Online (Sandbox Code Playgroud)

然后我使用Apache Commons来编写文件:

val source = new MyInputStream(dataStream)
val target = new FileOutputStream(file)
try {
  IOUtils.copy(source, target)
} finally {
  target.close
}
Run Code Online (Sandbox Code Playgroud)

这有效,但我对性能不太满意.我猜测调用MyInputStream.read每个字节会引入很多开销.有没有更好的办法?

Ste*_*man 6

您可能(或可能不会)错误地认为读取方是您性能问题的根源.可能是您正在使用无缓冲的FileOutputStream(...),强制对每个写入的字节进行单独的系统调用.

这是我的看法,快速简单:

def writeBytes( data : Stream[Byte], file : File ) = {
  val target = new BufferedOutputStream( new FileOutputStream(file) );
  try data.foreach( target.write(_) ) finally target.close;
}
Run Code Online (Sandbox Code Playgroud)


Aph*_*hex 5

我推荐这个java.nio.file包.随着Files.write你可以写ArrayBytes到一个Path从一个文件名构成.

这取决于你如何提供Bytes.您可以打开Stream变成一个Array.toArray或可以take字节off在时间的流里一个(或少数),并把他们变成阵列.

这是一个简单的代码块,演示了该.toArray方法.

import java.nio.file.{Files, Paths}

val filename: String = "output.bin"
val bytes: Stream[Byte] = ...
Files.write(Paths.get(filename), bytes.toArray)
Run Code Online (Sandbox Code Playgroud)

  • 我认为问题@mrog正面临着`.toArray`迫使流被物化到内存中而且它太大了. (2认同)