读取 BufferedReader 的内容时出现 NullPointerException,尽管它不是空的

NullPointerException while reading content of BufferedReader although it's not empty

每当我尝试获取我的 BufferedReader 的内容时,当我 运行 已经打包在 jar 中的项目时,我都会得到一个 NullPointerException。当它 运行s 在 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 at java.io.FilterInputStream.read(Unknown Source) at sun.nio.cs.StreamDecoder.readBytes(Unknown Source) at sun.nio.cs.StreamDecoder.implRead(Unknown Source) at sun.nio.cs.StreamDecoder.read(Unknown Source) at java.io.InputStreamReader.read(Unknown Source) at java.io.BufferedReader.fill(Unknown Source) at java.io.BufferedReader.readLine(Unknown Source) at java.io.BufferedReader.readLine(Unknown Source) at java.io.BufferedReader.hasNext(Unknown Source) at java.util.Iterator.forEachRemaining(Unknown Source) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Unknown Source) at java.util.stream.AbstractPipeline.copyInto(Unknown Source) at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source) at java.util.stream.AbstractPipeline.evaluate(Unknown Source) at java.util.stream.ReferencePipeline.collect(Unknown Source) at main.java.backend.Session.importFontResource(Session.java:137) at main.java.backend.Session.main(Session.java:180)

您打开资源 /fonts/Open_Sans 的 InputStream。

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

当你运行将代码打包到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 获得的输入流是扩展 FilterInputStreamsun.net.www.protocol.jar.JarURLConnection$JarURLInputStream 并且它不会清理其构造函数参数,这会在以后导致 NPE)。

您不能读取这样的资源目录。由于标准 java 中没有 easy 规定,请在资源文件中列出 "directory" 并阅读它。 保持常规。

对于 "uneasy" 解决方案:http://www.uofr.net/~greg/java/get-resource-listing.html

您可能需要考虑以其他方式打开流。当我想要一个 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();
}