【问题标题】:for-comprehension, guard and RandomAccessFile.readLinefor-comprehension、guard 和 RandomAccessFile.readLine
【发布时间】:2016-11-15 21:46:15
【问题描述】:

考虑以下几点:

有一个包含一定行数的文本文件,例如:

测试.txt: 一种 b C d e F G h

(每个都有自己的一行)

那么就有下面这个类用于解析:

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 条件,for 理解是否甚至可以循环直到给定次数或停止?

我的语法有问题吗?

【问题讨论】:

    标签: scala for-loop randomaccessfile for-comprehension


    【解决方案1】:

    如果你想坚持你的 parse 方法,你可以使用 getFilePointerlength

    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)
    

    【讨论】:

    • 啊,废话..我试图提供一个小例子,但我不想解决我的具体问题,而是一个通用的解决方案
    【解决方案2】:

    你可以将randomAccessFile.readLine封装在Option中,这样null就会变成Nonevalue变成Some(value)

    另外,Option 可以看作是一个集合,所以你可以把它和IndexedSeq 放在同一个地方理解:

    for {
      x <- 0 until readLines
      r <- Option(randomAccessFile.readLine())
    } yield r
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 2015-01-21
      • 1970-01-01
      • 2020-04-17
      相关资源
      最近更新 更多