我需要从128M的chuck文件中读取一些数据,然后对于每一行,我会做一些处理,天真的方法是使用split将字符串转换为行集合然后处理每一行,但也许这是无效的,因为它会创建一个简单存储临时结果的集合。有没有更好的表现方式?
文件很大,所以我开了几个线程,每个线程都会拿起128个chuck,在下面的脚本中rawString是一个128M的chuck。
randomAccessFile.seek(start)
randomAccessFile.read(byteBuffer)
val rawString = new String(byteBuffer)
val lines=rawString.split("\n")
for(line <- lines){
...
}
答案 0 :(得分:2)
最好逐行阅读文字:
import scala.io.Source
for(line <- Source.fromFile("file.txt").getLines()) {
...
}
答案 1 :(得分:1)
我不确定你要在块的开头和结尾处跟踪行的尾部。我会留给你弄清楚 - 这个解决方案通过\n
捕获双方划定的所有内容。
无论如何,假设byteBuffer
实际上是一个字节数组而不是java.nio.ByteBuffer
,并且你只需处理Unix行编码就可以了,你会想要
def lines(bs: Array[Byte]): Array[String] = {
val xs = Array.newBuilder[Int]
var i = 0
while (i<bs.length) {
if (bs(i)=='\n') xs += i
i += 1
}
val ix = xs.result
val ss = new Array[String](0 max (ix.length-1))
i = 1
while (i < ix.length) {
ss(i-1) = new String(bs, ix(i-1)+1, ix(i)-ix(i-1)-1)
i += 1
}
ss
}
当然这是一个相当漫长而混乱的代码,但是如果你真的担心性能这种事情(大量使用对基元的低级操作)是要走的路。 (这也只占磁盘上块大约3倍的内存而不是~5倍(大部分/完全是ASCII数据),因为你不需要周围的完整字符串表示。)