classLoader.getResourceasstream返回测试中的空流

发布于 2025-02-07 10:21:53 字数 1199 浏览 2 评论 0原文

我有一种方法需要读取资源文件并将其作为输入流传递给另一种方法。显而易见的方法

InputStream is = classLoader.getResourceAsStream("filename.pem");

在实际运行应用程序时可以正常工作,但是在测试时,它返回一个空输入式(填充零)。我认为资源路径或其他任何问题都不是问题,因为当我使用“ filex”(Filex不存在)时,我会得到实际的null指针异常,而不是空流。同样,在调试器中,空流的完整文件路径指向正确存储文件的正确路径(默认类root)。

此外,在以下解决方法的情况下,它可以工作:

            File file = new File(classLoader.getResource("filename.pem").getFile());
            String fileS= new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
            InputStream is = classLoader.getResourceAsStream("filename.pem");
            InputStream is2 = new ByteArrayInputStream(fileS.getBytes(StandardCharsets.UTF_8));

在此示例中,is2在InputStream中具有文件的实际内容,而is 具有填充零的流。我无法完全解释这种行为。如果我们在应用程序中使用一些修改后的classloader,我将与'getClass()。getClassLoader()。getClass()。

所以我的问题是:

  • 为什么解决方法可以起作用,而不是经典的方法?
  • 为什么仅在测试课程中失败?
  • 有没有办法使它起作用?解决方法是更多的代码行,也需要由于files.readallBytes()呼叫而需要捕获IOException。

我剩下的唯一想法是:编码或Charset与它有关。但据我所知,getResourceasstream()喜欢chods> charsetstandardCharsets

I have a method where I need to read a resource file and pass it to another method as an InputStream. The obvious approach

InputStream is = classLoader.getResourceAsStream("filename.pem");

works fine when actually running the application, but in testing it returns an empty InputStream (filled with zeros). I don't think its a problem with the resource path or anything, because when I use a nonsense path like "filex" (filex does not exist), I get an actual null pointer exception and not an empty stream. Also in debugger the complete file path of the empty Stream points to the correct path, where the file actually is stored (default class root).

Furthermore, with the following workaround it works:

            File file = new File(classLoader.getResource("filename.pem").getFile());
            String fileS= new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
            InputStream is = classLoader.getResourceAsStream("filename.pem");
            InputStream is2 = new ByteArrayInputStream(fileS.getBytes(StandardCharsets.UTF_8));

In this example is2 has the actual content of the file in the InputStream, while is has an Stream filled with zeros. I can't quite explain that behaviour. I double checked with 'getClass().getClassLoader().getClass()' if we use some modified ClassLoader in the Application, but it is the original one from sun.misc.Launcher$AppClassLoader.

So my questions are:

  • Why does the workaround work but not the classic approach?
  • Why does it fail only in test class?
  • Is there a way to make it work? The workaround is more lines of code and also need to catch IOException because of the Files.readAllBytes() call.

The only idea I had left: the encoding or charset has something to do with it. But to my knowledge there is no parameter in getResourceAsStream() like Charset or StandardCharsets.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

⊕婉儿 2025-02-14 10:21:53

如果将资源文件作为流打开,则最终会在BufferedInputStream周围围绕fileinputStream

呼叫链如下:

  • java.lang.classloader#getResource返回url
  • url.openstream()
  • 首先将其称为流。 ; sun.net.www.protocol.file.file.handler#createfileurlconnection
  • 然后连接流:is = new BufferedInputStream(new FileInputStream(fileName(filename)); in sun sun 。

BufferedInputStream,一旦您开始从InputStream读取,它就会立即使用。
参见 fileInputStream note note offileInputStream noted notefere >

例如,如果您从输入流读取所有零的读取物,您会看到它确实包含数据:

Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name());
String firstLine = scanner.next();

https://www.baeldung.com/convert-input-stream-to-string

您的解决方法可以正常工作,因为您实际上是从资源URL找到文件后,实际上可以直接开始读取它。

因此,您的测试可能会失败;您是否不尝试从测试柜中的流中阅读?您如何在测试中与实际应用程序中使用此输入流,您如何使用/验证?可能有问题。

If you open a resource file as a stream, you end up with a BufferedInputStream around a FileInputStream.

The call chain is as follows:

  • java.lang.ClassLoader#getResource returns an URL
  • url.openStream() is called
  • this first opens the Stream; sun.net.www.protocol.file.Handler#createFileURLConnection
  • then the Stream is connected: is = new BufferedInputStream(new FileInputStream(filename)); in sun.net.www.protocol.file.FileURLConnection#connect
  • finally you get this is back as InputStream

What you're seeing is the empty internal buffer of the BufferedInputStream, which will be used as soon as you start reading from the InputStream.
See is FileInputStream not buffered and why BufferedInputStream is faster?

If you for example read from the InputStream with all zero's, you will see it does actually contain data:

Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name());
String firstLine = scanner.next();

From https://www.baeldung.com/convert-input-stream-to-string

Your workaround works, because after you've located the file from the resource URL you actually start reading it directly.

So what might be failing in your test; are you not trying to read from the stream in your testcase? How are you using/validating if this inputstream is correct in your test vs the real application? There might be the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文