读取 JAR 文件之外的属性文件

我有一个 JAR 文件,其中所有代码都存档以便运行。我必须访问一个属性文件,它需要在每次运行之前更改/编辑。我希望将属性文件保存在 JAR 文件所在的同一目录中。是否可以告诉 Java 从该目录中获取属性文件?

注意: 我不想将属性文件保存在主目录中,也不想在命令行参数中传递属性文件的路径。

222303 次浏览

从 jar 文件访问文件目录中的文件总是有问题。在 jar 文件中提供类路径是非常有限的。相反,请尝试使用 bat 文件或 sh 文件启动程序。这样,您就可以随心所欲地指定类路径,引用系统上任何位置的任何文件夹。

还要看看我对这个问题的回答:

为包含 sqlite 的 java 项目创建.exe 文件

因此,您希望将同一文件夹中的 .properties文件作为 main/runnable jar 处理为文件,而不是作为 main/runnable jar 的资源。在这种情况下,我自己的解决方案如下:

首先: 您的程序文件体系结构应该是这样的(假设您的主程序是 main.jar,其主属性文件是 main.properties) :

./ - the root of your program
|__ main.jar
|__ main.properties

使用这种体系结构,您可以在 main.jar 运行之前或运行期间使用任何文本编辑器修改 main.properties 文件中的任何属性(取决于程序的当前状态) ,因为它只是一个基于文本的文件。例如,main.properties 文件可能包含:

app.version=1.0.0.0
app.name=Hello

因此,当你从根/基文件夹运行主程序时,通常你会这样运行它:

java -jar ./main.jar

或者,直接说:

java -jar main.jar

在 main.jar 中,需要为 main.properties 文件中找到的每个属性创建几个实用程序方法; 假设 app.version属性具有如下 getAppVersion()方法:

/**
* Gets the app.version property value from
* the ./main.properties file of the base folder
*
* @return app.version string
* @throws IOException
*/


import java.util.Properties;


public static String getAppVersion() throws IOException{


String versionString = null;


//to load application's properties, we use this class
Properties mainProperties = new Properties();


FileInputStream file;


//the base folder is ./, the root of the main.properties file
String path = "./main.properties";


//load the file handle for main.properties
file = new FileInputStream(path);


//load all the properties from this file
mainProperties.load(file);


//we have loaded the properties, so close the file handle
file.close();


//retrieve the property we are intrested, the app.version
versionString = mainProperties.getProperty("app.version");


return versionString;
}

在主程序中需要 app.version值的任何部分,我们调用它的方法如下:

String version = null;
try{
version = getAppVersion();
}
catch (IOException ioe){
ioe.printStackTrace();
}

我是用另一种方法做的。

Properties prop = new Properties();
try {


File jarPath=new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String propertiesPath=jarPath.getParentFile().getAbsolutePath();
System.out.println(" propertiesPath-"+propertiesPath);
prop.load(new FileInputStream(propertiesPath+"/importer.properties"));
} catch (IOException e1) {
e1.printStackTrace();
}
  1. 获取 Jar 文件路径。
  2. 获取该文件的父文件夹。
  3. 在 InputStreamPath 中使用具有属性文件名的路径。

我有一个类似的情况: 希望我的 *.jar文件访问该 *.jar文件旁边的目录中的一个文件。也请参考 这个答案

我的文件结构是:

./ - the root of your program
|__ *.jar
|__ dir-next-to-jar/some.txt

我能够加载一个文件(比如说,some.txt)到 *.jar文件中的 InputStream,具体如下:

InputStream stream = null;
try{
stream = ThisClassName.class.getClass().getResourceAsStream("/dir-next-to-jar/some.txt");
}
catch(Exception e) {
System.out.print("error file to stream: ");
System.out.println(e.getMessage());
}

然后做任何你想与 stream

我有一个通过类路径或使用 log4j2.properties 从外部配置实现这两种操作的示例

package org.mmartin.app1;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;


import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.LogManager;




public class App1 {
private static Logger logger=null;
private static final String LOG_PROPERTIES_FILE = "config/log4j2.properties";
private static final String  CONFIG_PROPERTIES_FILE = "config/config.properties";


private Properties properties= new Properties();


public App1() {
System.out.println("--Logger intialized with classpath properties file--");
intializeLogger1();
testLogging();
System.out.println("--Logger intialized with external file--");
intializeLogger2();
testLogging();
}








public void readProperties()  {
InputStream input = null;
try {
input = new FileInputStream(CONFIG_PROPERTIES_FILE);
this.properties.load(input);
} catch (IOException e) {
logger.error("Unable to read the config.properties file.",e);
System.exit(1);
}
}


public void printProperties() {
this.properties.list(System.out);
}


public void testLogging() {
logger.debug("This is a debug message");
logger.info("This is an info message");
logger.warn("This is a warn message");
logger.error("This is an error message");
logger.fatal("This is a fatal message");
logger.info("Logger's name: "+logger.getName());
}




private void intializeLogger1() {
logger = LogManager.getLogger(App1.class);
}
private void intializeLogger2() {
LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
File file = new File(LOG_PROPERTIES_FILE);
// this will force a reconfiguration
context.setConfigLocation(file.toURI());
logger = context.getLogger(App1.class.getName());
}


public static void main(String[] args) {
App1 app1 = new App1();
app1.readProperties();
app1.printProperties();
}
}




--Logger intialized with classpath properties file--
[DEBUG] 2018-08-27 10:35:14.510 [main] App1 - This is a debug message
[INFO ] 2018-08-27 10:35:14.513 [main] App1 - This is an info message
[WARN ] 2018-08-27 10:35:14.513 [main] App1 - This is a warn message
[ERROR] 2018-08-27 10:35:14.513 [main] App1 - This is an error message
[FATAL] 2018-08-27 10:35:14.513 [main] App1 - This is a fatal message
[INFO ] 2018-08-27 10:35:14.514 [main] App1 - Logger's name: org.mmartin.app1.App1
--Logger intialized with external file--
[DEBUG] 2018-08-27 10:35:14.524 [main] App1 - This is a debug message
[INFO ] 2018-08-27 10:35:14.525 [main] App1 - This is an info message
[WARN ] 2018-08-27 10:35:14.525 [main] App1 - This is a warn message
[ERROR] 2018-08-27 10:35:14.525 [main] App1 - This is an error message
[FATAL] 2018-08-27 10:35:14.525 [main] App1 - This is a fatal message
[INFO ] 2018-08-27 10:35:14.525 [main] App1 - Logger's name: org.mmartin.app1.App1
-- listing properties --
dbpassword=password
database=localhost
dbuser=user

这对我有用。从 current directory加载您的属性文件。

注意 : 方法 Properties#load 使用 ISO-8859-1编码

Properties properties = new Properties();
properties.load(new FileReader(new File(".").getCanonicalPath() + File.separator + "java.properties"));
properties.forEach((k, v) -> {
System.out.println(k + " : " + v);
});

确保 java.propertiescurrent directory。你只需要编写一个小的启动脚本,切换到正确的目录之前,像

#! /bin/bash
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $scriptdir
java -jar MyExecutable.jar
cd -

在项目中,只需将 java.properties文件放在项目根目录中,以便使这段代码也能在 IDE 中工作。

在这里,如果你提到 .getPath(),那么它将返回 Jar 和我猜想的路径 您将需要它的父文件来引用放置在 jar 中的所有其他配置文件。 此代码适用于 Windows。请在主类中添加代码。

File jarDir = new File(MyAppName.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String jarDirpath = jarDir.getParent();


System.out.println(jarDirpath);
File parentFile = new File(".");
String parentPath = file.getCanonicalPath();
File resourceFile = new File(parentPath+File.seperator+"<your config file>");