JARファイルの外でプロパティファイルを読み取る


131

すべてのコードが実行用にアーカイブされているJARファイルがあります。各実行前に変更/編集する必要があるプロパティファイルにアクセスする必要があります。プロパティファイルをJARファイルと同じディレクトリに保持したい。とにかくそのディレクトリからプロパティファイルを取得するようにJavaに指示するのですか?

注:プロパティファイルをホームディレクトリに保持したり、コマンドライン引数でプロパティファイルのパスを渡したりしたくありません。


2
この回答を参照してください- 「代わりに「デフォルト」ファイルをJar内に保存します。変更された場合は、変更されたファイルを別の場所に保存します。1つの一般的な場所はのサブディレクトリですuser.home。ファイルを確認するときは、最初にファイルシステム上の変更されたファイル。存在しない場合は、デフォルトのファイルをロードしてください。」 ところで 「私はしたくない..」あなたが望むものは、何が機能し実用的であるかほど重要ではありません。アプリを保存しています。アプリケーションディレクトリの設定は、OracleとMSの両方(おそらく他のユーザーも)が強く推奨していません。
アンドリュートンプソン

3
jarディレクトリーにプロパティー・ファイルを保持する必要があるのは、ディレクトリー全体(jarとpropertyを含む)が別のマシンにコピーされて実行されるときにそれらを一緒に保持する方が良いためです。
Neil

また、ユーザーにプロパティファイルのパスを渡すように強制した場合、別のマシンからバッチファイルを実行するたびに変更する必要があります。
Neil

回答:


144

したがって、.properties同じフォルダーにあるファイルを、メイン/実行可能な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

したがって、メインプログラムをroot / baseフォルダーから実行すると、通常は次のように実行されます。

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();
}

7
このソリューションは機能します。正確な要件と詳細なコードを理解していただきありがとうございます。プロパティファイルがjarファイル内にないことを確認しましたが、jarファイルと同じディレクトリからファイルにアクセスできることを確認しました。このように、絶対パスではなく、ハードコードが必要です。jarファイルとプロパティファイルの両方を任意のディレクトリにコピーして、個別に実行できるようになりました。
Neil

3
ex:{{java -jar build / main.jar}}の外部からコマンドを実行した場合、ファイルは見つかりません。@eee、それに対する修正はありますか?
Darian、2015

@Darianここで修正するものはありません。./ファイル構成アーキテクチャーで説明したものと同じルートフォルダー(同じディレクトリレベル)にjarファイルとプロパティファイルを配置する必要がある場合にのみ、設計どおりに機能します。(元のポスターで設定された要件による)
エクル2015

@Darianなので、を実行する場合は、jarと同じディレクトリレベルにjava -jar build/main.jarあるように、プロパティファイルもbuildフォルダに配置する必要があります。
エクル2015

7
@eeeの回答に感謝します。問題は、ユーザーがを実行する場所がわからないことjava -jar path/to/jar/fileです。しかし、私は別の質問で解決策を見つけました:String path = ClassLoader.getSystemClassLoader().getResource(".").getPath() + "/main.properties";
Darian

42

別の方法でやった。

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でそのパスを使用します。

getParentFile()部分を削除する必要があったので、代わりに次を使用しました。String propertiesPath = jarPath.getAbsolutePath(); しかし、それはすべて、ファイルの場所によって異なります
MobileMon '25

4
「jarPath.getParentFile()。getAbsolutePath();」を置き換えるだけです。「jarPath.getParent()」に。そのとき魅力のように機能します。
StackAddict 2015年

1
私の場合も同じですが、スプリングベースのプロジェクトがあります。Springにjarファイルの横にあることをどのように伝えるのですか?アイデア
Mubasher

3

jarファイルからファイルディレクトリのファイルにアクセスする場合、常に問題が発生します。jarファイルでのクラスパスの提供は非常に制限されています。代わりに、batファイルまたはshファイルを使用してプログラムを起動してみてください。このようにして、システム上の任意の場所にある任意のフォルダーを参照して、クラスパスを任意に指定できます。

また、この質問に対する私の答えを確認してください:

SQLiteを含むJavaプロジェクトの.exeファイルを作成する


1

私は同様のケースがあります。私の*.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


0

クラスパスまたは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

0

これでうまくいきます。プロパティファイルをロードするcurrent directory

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.propertiesですcurrent directory。次のように、前に正しいディレクトリに切り替える小さな起動スクリプトを書くだけです。

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

プロジェクトでは、java.propertiesこのコードをIDEからも機能させるために、ファイルをプロジェクトルートに配置するだけです。


0

ここで言及.getPath()すると、jarのパスが返されます。jarとともに配置された他のすべての構成ファイルを参照するには、その親が必要になると思います。このコードはWindowsで動作します。メインクラス内にコードを追加します。

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

System.out.println(jarDirpath);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.