我的程序通过从当前目录读取xml文件来读取配置数据:
File fXmlFile = new File("configFile.xml");
它在NetBeans IDE中正常工作。我已经建立了项目并得到了jar文件。如果我在Windows 10中双击它,它将运行良好。如果我通过右键单击jar打开文件,而Open with -> Java
程序找不到配置文件。在这种情况下,我出现了异常:
java.io.FileNotFoundException: C:\Windows\System32\configFile.xml (The system cannot find the file specified)
为什么它看起来只是系统路径而不是当前目录?在Open with -> Java
情况下运行时,如何要求程序将文件加载到当前目录中?
Jar的清单文件:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.10.4
Created-By: 12.0.1+12 (Oracle Corporation)
Class-Path: lib/log4j-api-2.11.2.jar lib/log4j-core-2.11.2.jar lib/met
ouia.jar lib/swt.jar
X-COMMENT: Main-Class will be added automatically by build
Main-Class: com.aaa.myprog.runMe
答案 0 :(得分:1)
正如Victor已经指出的那样,当前目录取决于用于启动JVM的命令,因此在运行时是动态的。相反,您需要一个依赖于jar文件本身位置的定位器,这意味着它在编译时是动态的,而在运行时是静态的。
这里有不同的方法,所以让我简短介绍两种:
使用启动脚本
这样,您只需要自己控制命令行即可,但是您必须在计划使用程序的每个操作系统上进行控制。在Windows上看起来可能像这样:
app.bat:
cd %~dp0
java -jar app.jar
第一行here上的更多信息。
使用系统ClassLoader
之所以可行,是因为System ClassLoader的源在编译时是动态的,而在运行时是静态的,因此正是您所需要的。但是,这样做的缺点是,您只能写入InputStream
,因此无法写入配置文件。
app.jar
try (InputStream fXml = ClassLoader.getSystemClassLoader().getResourceAsStream("configFile.xml")) {
...
}
还有完整的MCVE。
ConfigFile.java:
public class ConfigFile {
public static void main(String[] args) {
try (final BufferedReader configFile = new BufferedReader(
new InputStreamReader(ClassLoader.getSystemClassLoader()
.getResourceAsStream("configFile.txt")))) {
System.out.println(configFile.readLine());
} catch (final IOException exc) {
exc.printStackTrace();
}
}
}
ConfigFile.txt
Hello World
MANIFEST.MF
Manifest-Version: 1.0
Class-Path: .
Main-Class: prv.izruo.test.ConfigFile
命令行
P:\workspace\ConfigFile>dir deploy
...
02.05.2019 20:43 1.434 configFile.jar
02.05.2019 20:43 11 configFile.txt
P:\workspace\ConfigFile>java -jar deploy\configFile.jar
Hello World
答案 1 :(得分:1)
阅读for (int i = 0; i < 100000; i ++)
{
// Set the cursor to the beginning (0) of the current line (Console.CursorTop)
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write("count: " + i);
}
和应用程序可能需要的其他资产的最佳方法是将它们放在config.xml
中,然后将它们作为类路径中的文件引用,如下所示:
src/main/resources
mv configFile.xml /users/vico/my_program/src/main/resources
(此代码是从volumes借来的)
然后,您可以将jar移到任意位置,甚至将其运送给用户,而不必担心配置文件的位置。
答案 2 :(得分:-1)
我看到问题的出现是因为您需要了解在执行时如何解析相对路径,并且在此引用中会出现“当前目录”,所以请允许我解释一下
据我所知,“当前目录”也称为工作目录,它是在启动Java应用程序时设置的,它假定执行目录的值Java命令启动应用程序。
例如:
如果打开命令终端,然后将自己置于目录"C:\pepe"
中,然后从该目录中执行命令以启动jar,例如:java -jar "c:\path\to\my\app.jar"
,则工作目录为{ {1}},并且在您的程序中,所有对相对路径的引用都将使用"c:\pepe\"
前缀来完成。
然后,它们的行"c:\pepe\"
将指示jvm在File fXmlFile = new File("configFile.xml");
处查找文件,因为相对路径"c:\pepe\configFile.xml"
将使用工作目录来解析(先前在启动时设置) ),如上所述。
请记住java如何使用工作目录作为前缀来设置工作目录以及如何解析相对路径,从现在开始帮助您解决任何引用问题!
您可能会发现此链接有用:Getting the Current Working Directory in Java用于调查netbeans在为我们启动Java应用程序时设置的工作目录是什么。
TD; DR:
“ pepe”是西班牙语,等于英语中的“ foo”:D,希望学点新知识! :D