语境
我检测到File.separator
在编译为可运行 jar 的一段代码中使用时的奇怪行为。
对于上下文,我有一个 xml 支持的数据库。然后程序与该数据库进行交互,在开始时解析整个文档,创建对象,修改它们,然后在程序结束时更新 xml 文件。
实际内容和/或文件类型实际上无关紧要,但我已经包含了一个简单的 Hello World txt 作为示例。无论哪种方式,该文件都被数据库读取为InputStream
(唯一的区别是我从 that 解析实际的 xml InputStream
)。
MWE
数据库.java
import java.io.File;
import java.io.InputStream;
public class Database {
public InputStream getInputStreamDependentSeparator(String fileName) {
return getClass().getResourceAsStream("/resources/" + fileName);
}
public InputStream getInputStreamIndependentSeparator(String fileName) {
return getClass().getResourceAsStream("/resources" + File.separator + fileName);
}
}
主.java
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
Database db = new Database();
InputStream is1 = db.getInputStreamDependentSeparator("HelloWorld.txt");
InputStream is2 = db.getInputStreamIndependentSeparator("HelloWorld.txt");
System.out.println(is1.toString());
System.out.println(is2.toString());
}
}
你好世界.txt
Hello World!
问题描述
is1
用于/
分隔目录,而is2
使用File.separator
- 通过 IDE (Eclipse) 运行,这两个语句都不会导致异常,并产生以下输出:
java.io.BufferedInputStream@5305068a
java.io.BufferedInputStream@1f32e575
- 将代码编译为可运行的 jar(在 Eclipse 中,右键单击项目,左键单击导出,然后按照提示输入可运行的 jar),然后从命令行运行会导致
NullPointerException
抛出is2
. 这是以下输出:
java -jar fileSeparator.jar
sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@85ede7b
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Object.toString()" because "is2" is null
at Main.main(Main.java:12)
- 请注意,该
System.out.println();
语句并不意味着实际给出HelloWorld.txt
文件的内容,只是为了检查是否InputStream
有效或触发异常
问题
- 直接从Oracle引用:编辑:正如 Erwin Bolwidt 指出的,这是关于 atg 的,不适用于 jdk。很抱歉没有注意到这一点。
为文件属性指定值时,Nucleus 将正斜杠 (/) 转换为您平台的文件分隔符(例如,Windows 使用反斜杠 (\) 作为文件分隔符)。
- 这意味着两者都
File.separator
应该/
提供相同的结果。但是,MWE 显示前者在运行 jar 时不起作用,而后者在 IDE 和 jar 中都可以工作。这是一个错误吗?或者我错过了什么,这是实际的预期行为? - 我一直在使用
File.separator
,根据这篇文章,这是确保未来平台兼容性的最安全方法。无论这是错误还是实际预期的行为,我应该如何解决这个问题?(我可以只使用/
,但我又会失去平台独立性......)