JAR dosyası dışındaki özellikler dosyasını oku


131

Tüm kodumun çalıştırılmak üzere arşivlendiği bir JAR dosyam var. Her çalıştırmadan önce değiştirilmesi / düzenlenmesi gereken bir özellikler dosyasına erişmem gerekiyor. Özellikler dosyasını JAR dosyasının bulunduğu dizinde tutmak istiyorum. Java'ya bu dizinden özellikler dosyasını almasını söylemek mümkün mü?

Not: Özellikler dosyasını ana dizinde tutmak veya özellikler dosyasının yolunu komut satırı bağımsız değişkeninde iletmek istemiyorum.


2
Bu yanıta bakın - "Bunun yerine, 'varsayılan' dosyayı Jar'ın içinde saklayın. Değiştirilmişse, değiştirilen dosyayı başka bir yerde saklayın. Yaygın bir yer, alt dizinidir user.home. Dosyayı kontrol ederken, önce şu dosyanın varlığını kontrol edin: dosya sisteminde değiştirilmiş bir dosya ve yoksa, varsayılan dosyayı yükleyin. " BTW "İstemiyorum .." İstediğiniz, işe yarayan ve pratik olan şeyden daha az önemlidir. Uygulama kaydediliyor. uygulama dizinindeki ayarlar, hem Oracle hem de MS (ve muhtemelen diğerleri) tarafından kesinlikle önerilmez.
Andrew Thompson

3
Özellikler dosyasını jar dizininde tutmamın nedeni, tüm dizin (jar ve özellik dahil) başka bir makineye kopyalanıp çalıştırıldığında onları bir arada tutmanın daha iyi olmasıdır.
Neil

Ve eğer kullanıcıyı özellik dosyası yolunu geçmeye zorlarsam, toplu iş dosyasını farklı bir makineden her çalıştırdığında onu değiştirmesi gerekir.
Neil

Yanıtlar:


144

Yani, tedavi etmek istiyorsun .properties dosyanızı ana / çalıştırılabilir kavanozun bir kaynağı yerine bir dosya olarak ana / çalıştırılabilir kavanozla aynı klasörde . Bu durumda benim çözümüm şu şekilde:

Öncelikle ilk şey: program dosya mimariniz şöyle olacaktır (ana programınızın main.jar ve ana özellikler dosyasının main.properties olduğunu varsayarak):

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

Bu mimari ile, main.properties dosyasındaki herhangi bir özelliği, yalnızca metin tabanlı bir dosya olduğundan, main.jar'ınız çalışmadan önce veya çalışırken (programın mevcut durumuna bağlı olarak) herhangi bir metin düzenleyicisini kullanarak değiştirebilirsiniz. Örneğin, main.properties dosyanız şunları içerebilir:

app.version=1.0.0.0
app.name=Hello

Dolayısıyla, ana programınızı kök / temel klasöründen çalıştırdığınızda, normalde şu şekilde çalıştırırsınız:

java -jar ./main.jar

veya hemen:

java -jar main.jar

Main.jar dosyanızda, main.properties dosyanızda bulunan her özellik için birkaç yardımcı yöntem oluşturmanız gerekir; diyelim ki app.versionmülk getAppVersion()aşağıdaki gibi bir metoda sahip olacak :

/**
 * 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;
}

Ana programın app.versiondeğere ihtiyaç duyan herhangi bir bölümünde , yöntemini şu şekilde adlandırıyoruz:

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

7
Bu çözüm işe yarıyor. Gereksinimi ve ayrıntılı kodu tam olarak anladığınız için teşekkürler. Özellikler dosyasının jar dosyasının içinde olmadığını, ancak yine de jar dosyasının bulunduğu dizinden dosyaya erişebildiğini doğruladım. Bu şekilde mutlak yol sabit kodu gerekli değildir. Hem jar hem de özellik dosyası artık herhangi bir dizine kopyalanabilir ve bağımsız olarak çalıştırılabilir.
Neil

3
Örneğin, komutu dışarıdan çalıştırırsanız dosya bulunamadı: {{java -jar build / main.jar}}. Bunun için herhangi bir düzeltmen var mı @eee?
Darian

@Darian Burada düzeltilecek bir şey yok; Yalnızca jar ve özellikler dosyasının ./, dosya organizasyon mimarisinde anlattığımla aynı kök klasörde (aynı dizin düzeyinde) olması gerektiği durumlarda tasarlandığı şekilde çalışır . (orijinal gönderen tarafından belirlenen gereksinime göre)
ecle

@Darian, eğer yürütmek java -jar build/main.jaristiyorsanız, özellikler dosyasını buildda jar ile aynı dizin seviyesinde olması için klasöre koymanız gerekir .
ecle

7
Cevabınız için teşekkürler @eee, sorun şu ki, kullanıcının java -jar path/to/jar/file. Ama çözümü başka bir soruda buldum:String path = ClassLoader.getSystemClassLoader().getResource(".").getPath() + "/main.properties";
Darian

42

Ben başka şekilde yaptım.

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 dosya yolunu alın.
  2. Bu dosyanın Ana klasörünü alın.
  3. Bu yolu, özellikler dosya adınızla InputStreamPath'te kullanın.

GetParentFile () bölümünü bırakmak zorunda kaldım, bu yüzden onun yerine kullandım: String propertiesPath = jarPath.getAbsolutePath (); ancak hepsi dosyanın bulunduğu yere bağlıdır
MobileMon

4
Sadece "jarPath.getParentFile (). GetAbsolutePath ();" "jarPath.getParent ()" olarak. Tılsım gibi çalışıyor o zaman.
StackAddict

1
Benim durumumda da aynı Sorun var ama yay temelli projem var. Spring'e dosyanın jar dosyasının yanında olduğunu nasıl anlarım? herhangi bir fikir
Mubasher

3

Dosya dizininizdeki dosyalara bir jar dosyasından erişirken her zaman bir sorun vardır. Bir jar dosyasında sınıf yolunu sağlamak çok sınırlıdır. Bunun yerine, programınızı başlatmak için bir bat dosyası veya bir sh dosyası kullanmayı deneyin. Bu şekilde, sistemin herhangi bir yerindeki herhangi bir klasöre başvurarak, sınıf yolunuzu istediğiniz gibi belirtebilirsiniz.

Ayrıca bu soruya cevabımı kontrol edin:

sqlite içeren java projesi için .exe dosyası oluşturma


1

Benzer bir durumum var: dosyamın *.jarsöz konusu *.jardosyanın yanındaki bir dizindeki bir dosyaya erişmesini istemek . BU CEVAP'a bakın da .

Dosya yapım:

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

Aşağıdakilerle dosyanın some.txtiçindeki bir InputStream'e bir dosya (diyelim ki ) yükleyebiliyorum *.jar:

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

O zaman ne yaparsan yap stream


0

Hem sınıf yolu hem de log4j2.properties ile harici yapılandırmadan yapma örneğim var

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

Bu benim için çalışıyor. Özellikler dosyanızı şuradan yükleyin: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);
        });

O, emin olun java.propertiesyer almaktadır current directory. Daha önce doğru dizine geçiş yapan küçük bir başlangıç ​​betiği yazabilirsiniz, örneğin

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

java.propertiesProjenizde, bu kodun IDE'nizden de çalışmasını sağlamak için dosyayı proje kökünüze koyun .


0

Burada söz ederseniz .getPath(), bu Jar'ın yolunu geri getirecektir ve sanırım jar ile yerleştirilmiş diğer tüm yapılandırma dosyalarına başvurmak için ebeveynine ihtiyacınız olacak. Bu kod Windows'ta çalışır. Kodu ana sınıfa ekleyin.

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

System.out.println(jarDirpath);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.