请考虑以下事项:
有一个包含一定行数的文本文件,例如:
的test.txt: 一个 b C d Ë F G ħ
(每个都在自己的行中)
然后有以下用于解析的类:
class MyAwesomeParser
{
def parse(fileName: String, readLines: Int): IndexedSeq[String] =
{
val randomAccessFile = new RandomAccessFile(fileName, "r")
val x: IndexedSeq[String] = for
{
x <- 0 until readLines
r = randomAccessFile.readLine()
} yield r
x
}
}
以下是测试:
class MyAwesomeParserTest extends WordSpec
{
"MyAwesomeParser" when {
"read" should {
"parse only specified number of lines" in {
val parser = new EdgeParser("")
val x = parser.parse("test.txt", 5)
assert(x.size == 5)
}
}
"MyAwesomeParser" when {
"read" should {
"parse only until end of file" in {
val parser = new EdgeParser("")
val x = parser.parse("test.txt", 10)
assert(x.size == 8)
}
}
}
}
第二次测试是有问题的。当然,你说,你在这里错过了一名警卫......好吧,如果我加上
x <- 0 until readLines if randomAccessFile.readLine != null
到实现然后它会跳过几行,因为readLine已经消耗了这一行。
r = randomAccessFile.readLine
x <- 0 until readLines if r != null
不会遗憾地工作,因为第一行必须分配才能理解。
现在我想知道,是否有可能在理解之前循环直到给定的时间或者在基于readLine != null
条件之前停止?
我的语法坏了吗?
答案 0 :(得分:3)
如果您想坚持使用parse
方法,可以使用getFilePointer
和length
def parse(fileName: String, readLines: Int): IndexedSeq[String] =
{
val randomAccessFile = new RandomAccessFile(fileName, "r")
val x: IndexedSeq[String] = for
{
x <- 0 until readLines if randomAccessFile.getFilePointer < randomAccessFile.length
r = randomAccessFile.readLine()
} yield r
x
}
但是,我建议您只使用scala.io.Source
:
def parse(fileName: String, readLines: Int): Iterator[String] =
Source.fromFile(fileName).getLines.take(readLines)
答案 1 :(得分:2)
您可以将randomAccessFile.readLine
封装在Option
中,以便将null
更改为None
,将value
更改为Some(value)
。
此外,Option
可以被视为一个集合,因此您可以将其置于与IndexedSeq
相同的理解中:
for {
x <- 0 until readLines
r <- Option(randomAccessFile.readLine())
} yield r