【问题标题】:NullPointerException while reading content of BufferedReader although it's not empty读取 BufferedReader 的内容时出现 NullPointerException,尽管它不是空的
【发布时间】:2016-11-03 21:32:23
【问题描述】:

当我运行已打包在 jar 中的项目时,每次尝试获取 BufferedReader 的内容时都会收到 NullPointerException。当它在 IDE (IntelliJ) 中运行时没有任何问题。我已经检查了所有以前的 InputStreams,它们似乎没问题。你有小费吗?提前谢谢!

String pathToFontDir = "/fonts/Open_Sans";
GraphicsEnvironment localGE = GraphicsEnvironment.getLocalGraphicsEnvironment();
final InputStream is = Session.class.getResourceAsStream(pathToFontDir);
if(is != null){

        final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
        final BufferedReader br = new BufferedReader(isr);

        List fonts = br.lines().collect(Collectors.toList()); //throws NullPointerException
        if(fonts.size() > 0){
            for(Object font: fonts){
                InputStream fis = loader.getResourceAsStream(pathToFontDir + "/" + font);
                localGE.registerFont(Font.createFont(Font.TRUETYPE_FONT, fis));
            }
        } else{
            throw new IOException("Der angegebene Ordner enthält keine Schriftdateien!");
        }
    }

我也试着检查一下,我的 BufferedReader 是否包含任何内容,但它再次抛出异常而没有返回任何行:

        String fontName;
        while((fontName = br.readLine()) != null) //throws NPE as well
            System.out.println(fontName);

堆栈跟踪:

java.lang.NullPointerException 在 java.io.FilterInputStream.read(未知来源) 在 sun.nio.cs.StreamDecoder.readBytes(未知来源) 在 sun.nio.cs.StreamDecoder.implRead(未知来源) 在 sun.nio.cs.StreamDecoder.read(未知来源) 在 java.io.InputStreamReader.read(未知来源) 在 java.io.BufferedReader.fill(未知来源) 在 java.io.BufferedReader.readLine(未知来源) 在 java.io.BufferedReader.readLine(未知来源) 在 java.io.BufferedReader$1.hasNext(未知来源) 在 java.util.Iterator.forEachRemaining(未知来源) 在 java.util.Spliterators$IteratorSpliterator.forEachRemaining(未知来源) 在 java.util.stream.AbstractPipeline.copyInto(未知来源) 在 java.util.stream.AbstractPipeline.wrapAndCopyInto(未知来源) 在 java.util.stream.ReduceOps$ReduceOp.evaluateSequential(未知来源) 在 java.util.stream.AbstractPipeline.evaluate(未知来源) 在 java.util.stream.ReferencePipeline.collect(未知来源) 在 main.java.backend.Session.importFontResource(Session.java:137) 在 main.java.backend.Session.main(Session.java:180)

【问题讨论】:

  • 您确定所需文件已复制到 JAR 文件中吗?
  • 是的,确实,我已经检查过一次了。
  • 所以,本质上您是在尝试读取Open_Sans 文件,对吗?这就是失败的原因?
  • 嗯,是的,不是的,因为InputStream和InputStreamReader没有问题,我的控制台显示它们存在,甚至BufferedReader也存在,但我无法从中得到任何东西。它在调用 BR.lines().collect() 或 BR.readLine() 时抛出 NPE
  • 所以看起来好像目录 Open_Sans 将存在于我的 JAR 中,但它是空的,但它不是。

标签: java jar nullpointerexception bufferedreader getresource


【解决方案1】:

您为资源 /fonts/Open_Sans 打开一个 InputStream。

在 IDE 中运行时,该资源是一个目录。似乎 - 我不知道 - 它返回该目录中所有文件的列表。

当您运行打包在 jar 中的代码时,资源指向 Jar 文件中的目录条目。该资源的 InputStream 不为空,但是当您开始从中读取时,会抛出 NPE:

Exception in thread "main" java.lang.NullPointerException
    at java.io.FilterInputStream.read(FilterInputStream.java:133)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)

(您从getResourceAsStream 获得的输入流是一个sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream,它扩展了FilterInputStream,它不会清理其构造函数参数,这会导致稍后出现NPE)。

【讨论】:

  • +1 - Seems - I did not know that - that it returns a list of all files in that directory. 我也不是...当我尝试它时非常惊讶...
  • 是的,你完全正确,我只是查看了异常的堆栈跟踪并意识到了这一点。
【解决方案2】:

您不能像这样读取资源目录。由于标准 java 中没有 easy 规定,因此在资源文件中创建一个“目录”列表,然后阅读它。 保持常规。

对于“不安”的解决方案:http://www.uofr.net/~greg/java/get-resource-listing.html

【讨论】:

  • 谢谢,我会试试的! :)
【解决方案3】:

您可能需要考虑以其他方式打开流。当我想要从自身读取 JAR 或类路径时,我使用这个链:

File classpathBase = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());

一旦你有了它,它要么是一个 Jar 文件,要么是一个目录。从那里,您可以使用类似于此方法的某些方法来读取资源:

String resourceName = "/fonts/Open_Sans";
InputStream in;
JarFile jarFile = null;
if (classpathBase.isDirectory()){
   in = new FileInputStream(classPathBase.getPath() + resourceName);
} else {
   jarFile = new JarFile(file);
   JarEntry entry = jarFile.getEntry(resourceName);
   in = jarFile.getInputStream(entry);
}
// read from in.read()
in.close();
if (jarFile != null){
    jarFile.close();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    相关资源
    最近更新 更多