使用Source.fromResource从文件读取时处理NullPointerException

时间:2018-07-06 16:41:10

标签: scala

从不存在的文件中读取时,我发现width方法有奇怪的行为。据我了解,它应该返回Source.fromResource(),所以我将其包装到null中。但是当匹配它时,它被识别为Option,我得到Some

ReadFromFileExample.scala:

NullPointerException

如何解释这种行为?

UPD

我错了。它应返回类型为object ReadFromFileExample extends App { import scala.io.Source val sourceOpt = Option(Source.fromResource("non_existing_file.txt")) assert (sourceOpt.isDefined) // but it should return false sourceOpt match { case Some(source) => source.getLines() case None => throw new RuntimeException("Error reading from file") } } 的非null值。但是我怀疑它可以返回类型BufferedSource的值null。我不明白它如何返回BufferedLineIterator而不是NullPointerException

2 个答案:

答案 0 :(得分:1)

好吧,经过深思后,我得出结论,最好使用Try而不是Option,因为它会捕获任何异常

解决方案:

import scala.util.{Failure, Success, Try}

object ReadFromFileExample extends App {

  import scala.io.Source

  Try(Source.fromResource("non_existing_file.txt").getLines()) match {
    case Success(lines) => // handling lines
    case Failure(e) => println(s"An error has occured, cause: $e")
  }
}

更新

我已经弄清楚如何致电NullPointerException时得到getLines()

调用方法fromResource时,下面将调用方法classLoader.getResourceAsStream()。如果文件不存在,它将返回InputStream,即null

根据下面的堆栈跟踪,将此InputStream传递到Reader构造函数,在该构造函数中用作要同步的对象,即lock字段。如果是null,将抛出NullPointerException

Reader.java

//...

protected Reader(Object lock) {
    if (lock == null) {
        throw new NullPointerException();
    }
    this.lock = lock;
}

//...

Stacktrace (来自我的问题摘录):

Exception in thread "main" java.lang.NullPointerException
    at java.io.Reader.<init>(Reader.java:78)
    at java.io.InputStreamReader.<init>(InputStreamReader.java:129)
    at scala.io.BufferedSource.reader(BufferedSource.scala:22)
    at scala.io.BufferedSource.bufferedReader(BufferedSource.scala:23)
    at scala.io.BufferedSource.charReader$lzycompute(BufferedSource.scala:33)
    at scala.io.BufferedSource.charReader(BufferedSource.scala:31)
    at scala.io.BufferedSource.scala$io$BufferedSource$$decachedReader(BufferedSource.scala:60)
    at scala.io.BufferedSource$BufferedLineIterator.<init>(BufferedSource.scala:65)
    at scala.io.BufferedSource.getLines(BufferedSource.scala:84)
    at ReadFromFileExample$.delayedEndpoint$ReadFromFileExample$1(ReadFromFileExample.scala:12)

答案 1 :(得分:0)

用Try(Source.fromFile(...))替换Option(Source.fromResource(...))

import scala.io.Source

val sourceTry = Try(Source.fromFile("non_existing_file.txt"))

sourceTry match {
  case Success(source) => source.getLines()
  case Failure(f) => println(f.getMessage)
}