【发布时间】:2018-12-14 04:31:42
【问题描述】:
我为我的Javalin 应用程序构建了一个JAR 文件,代码运行良好。但是,从 JAR 中读取一些资源文件会失败并显示 inputStream.available() == 0,但它对其他一些文件也能正常工作。
以下文件应该是正确的:
a/
|\
| +- a.txt
| +- b.js
| +- c.css
|
b/
\
+- d.png
+- e.txt
但是,InputStream 仅读取文件a/a.txt、a/b.js 和b/e.txt。对于所有其他文件,它什么都不返回,@ 987654331@,但是当我不是从 JAR 中读取文件而是从提取的 Classpath 中读取文件时它可以工作(并且无论执行环境看起来如何,我都在使用 ClassLoader喜欢)。另外,文件大小无关紧要,a/a.txt 比a/c.css 大得多,所以我没有这方面的线索。
一些示例代码(正如我所说,我使用Javalin 处理HTTP 请求/响应,它在ctx 对象中处理,我还使用Apache Tika 来检测MIME-Type请求的文件,按预期工作):
// Example, real path is (correctly) fetched from the Context (ctx) object
String path = "a/c.css";
ClassLoader classLoader = Thread.currentThread ().getContextClassLoader ();
InputStream inputStream = classLoader.getResourceAsStream (path);
String contentType = tika.detect (inputStream, path);
ctx.header ("Content-Type", contentType);
if (contentType.contains ("text") || contentType.contains ("script")) {
InputStreamReader streamReader = new InputStreamReader (inputStream);
BufferedReader reader = new BufferedReader (streamReader);
String line;
StringBuilder builder = new StringBuilder ();
while ((line = reader.readLine ()) != null) {
builder.append (line).append ("\n");
}
String result = builder.toString ();
ctx.header ("Content-Length", String.valueOf (result.length ()));
ctx.result (result);
reader.close ();
} else {
ctx.header ("Content-Length", String.valueOf (inputStream.available ()));
ctx.result (inputStream);
}
我在这里遗漏了什么还是我做错了什么?
【问题讨论】:
-
available() 不会做你认为它做的事情。事实上,你可以说它没有用。所以,如果你使用它,你做错了什么,它不会工作。尽量不要使用它,并用其他东西代替你认为你正在用它做的任何事情。那会奏效的。
-
但是,HTTP 客户端没有收到任何内容。事实上,所有具有
available() == 0的文件的响应在从 JAR 中读取时都是 0 字节长。无论如何,当我从中删除available()的所有用法时,我的代码仍然无法从 JAR 中运行(让 Jetty 计算Content-Length)... -
显然
tika.detect()正在消耗输入流中的字节:在某些情况下,所有字节。 -
@EJP 我敢打赌,文本文件会检测到这一点。 InputStream 提供了 mark(),它很可能适用于所有 Java 实现的 jar 资源,而 Tika 最有可能使用它。
-
@AlexanderLeithner 对具有 available() == 0 的文件的响应是空的,因为您声明它们的长度为零字节。当你不使用 available() 时,你能展示你的代码是什么样的吗?“不起作用”到底是什么意思?你的代码真的不应该去翻转汉堡。它只是假设在给定一些输入的情况下产生一些输出。
标签: java jar inputstream javalin