在Scala中,读取文本文件并将其上传到数组中,一种常见的方法是
scala.io.Source.fromFile("file.txt").getLines.toArray
特别是对于非常大的文件,是否有一种更快的方法,可以先将字节块读取到内存中,然后用换行符将其拆分?(有关常用方法,请参阅Scala中的读取整个文件。)
非常感谢。
性能问题与读取数据的方式无关。它已被缓冲。在你真正迭代这些行之前,什么都不会发生:
// measures time taken by enclosed code
def timed[A](block: => A) = {
val t0 = System.currentTimeMillis
val result = block
println("took " + (System.currentTimeMillis - t0) + "ms")
result
}
val source = timed(scala.io.Source.fromFile("test.txt")) // 200mb, 500 lines
// took 0ms
val lines = timed(source.getLines)
// took 0ms
timed(lines.next) // read first line
// took 1ms
// ... reset source ...
var x = 0
timed(lines.foreach(ln => x += ln.length)) // "use" every line
// took 421ms
// ... reset source ...
timed(lines.toArray)
// took 915ms
考虑到我的硬盘驱动器的读取速度为每秒500mb,200mb的最佳时间为400ms,这意味着除了不将迭代器转换为数组之外,没有改进的余地。
根据您的应用程序,您可以考虑直接使用迭代器而不是数组。因为在内存中使用如此巨大的数组肯定会带来性能问题。
编辑:根据您的评论,我认为您希望进一步转换数组(可能会像您所说的读取数字数组那样将行拆分为列)。在这种情况下,我建议在阅读时进行转换。例如:
source.getLines.map(_.split(",").map(_.trim.toInt)).toArray
比快很多
source.getLines.toArray.map(_.split(",").map(_.trim.toInt))
(对我来说是1.9秒,而不是2.5秒)因为你不会把一个巨大的数组转换成另一个数组,而是把每一行单独转换,最后变成一个数组(只占用一半的堆空间)。此外,由于读取文件是一个瓶颈,因此在读取时进行转换的好处是可以提高CPU利用率。