Med*_*her 4 java file-io scala
我正在尝试使用scala处理大型二进制文件.如果可能的话,我想使用功能方法.我的主要方法现在看起来像这样:
def getFromBis( buffer:List[Byte], bis:BufferedInputStream ):(Byte,List[Byte],Boolean) = {
buffer match {
case Nil =>
val buffer2 = new Array[Byte](100000)
bis.read(buffer2) match {
case -1 => (-1,Nil,false)
case _ =>
val buffer3 = buffer2.toList
(buffer3.head,buffer3.tail,true)
}
case b::tail => return (b,tail,true)
}
}
Run Code Online (Sandbox Code Playgroud)
它需要一个列表缓冲区和一个缓冲的输入流.如果缓冲区不为空,它只返回head和tail,如果它为空,则从文件中获取下一个块,并将其用作缓冲区.
正如您所看到的,这不是很实用.我试图以尽可能少的潜在io调用的方式这样做,这就是为什么我以一种分块的方式做这件事.这里的问题是新的数组.每次我运行该函数时它都会创建一个新数组,并且随着程序运行时不断增加的内存使用情况来判断,我不认为它们会被破坏.
我的问题是:有没有更好的方法来使用scala以分块方式阅读大文件?我想保持一个完全功能性的方法,但至少我需要一个功能,它可以充当我的功能程序的其余部分的黑盒子.
你几乎肯定不想在a中存储字节List.每个字节都需要一个新对象.这样效率非常低,并且可能会导致内存使用量超过您需要的20倍.
最简单的方法是创建一个存储内部状态的迭代器:
class BisReader(bis: BufferedInputStream) {
val buffer = new Array[Byte](100000)
var n = 0
var i = 0
def hasNext: Boolean = (i < n) || (n >= 0 && {
n = bis.read(buffer)
i = 0
hasNext
})
def next: Byte = {
if (i < n) {
val b = buffer(i)
i += 1
b
}
else if (hasNext) next
else throw new IOException("Input stream empty")
}
}
implicit def reader_as_iterator(br: BisReader) = new Iterator[Byte] {
def hasNext = br.hasNext
def next = br.next
}
Run Code Online (Sandbox Code Playgroud)
可能有BisReader扩展Iterator [Byte],但由于Iterator不是专门的,这将需要装箱原始next/hasNext访问.这样,您可以在需要时以全速访问低级别(next/hasNext),否则使用方便的迭代器方法.
现在,您已经将具有干净界面的丑陋的非功能性Java IO内容隔离在一个类中,并且可以恢复正常运行.
编辑:当然,除了IO依赖于顺序并且有副作用,但是之前的方法也没有解决这个问题.
| 归档时间: |
|
| 查看次数: |
1753 次 |
| 最近记录: |