Как получить путь к работающему файлу JAR? - PullRequest
535 голосов
/ 26 ноября 2008

Мой код выполняется внутри JAR-файла, скажем, foo.jar, и мне нужно знать, в коде, в какой папке находится запущенный foo.jar.

Итак, если foo.jar находится в C:\FOO\, я хочу получить этот путь независимо от того, какой у меня текущий рабочий каталог.

Ответы [ 27 ]

1 голос
/ 14 декабря 2015

Что разочаровывает, так это то, что когда вы разрабатываете в Eclipse, MyClass.class.getProtectionDomain().getCodeSource().getLocation() возвращает каталог /bin, что прекрасно, но когда вы компилируете его в jar, путь включает в себя часть /myjarname.jar, которая дает вам недопустимый файл имена.

Чтобы код работал как в ide, так и после его компиляции в jar, я использую следующий фрагмент кода:

URL applicationRootPathURL = getClass().getProtectionDomain().getCodeSource().getLocation();
File applicationRootPath = new File(applicationRootPathURL.getPath());
File myFile;
if(applicationRootPath.isDirectory()){
    myFile = new File(applicationRootPath, "filename");
}
else{
    myFile = new File(applicationRootPath.getParentFile(), "filename");
}
0 голосов
/ 14 мая 2015

Подход getProtectionDomain может иногда не работать, например когда вам нужно найти jar для некоторых базовых java-классов (например, в моем случае StringBuilder класс в IBM JDK), однако следующее работает без сбоев:

public static void main(String[] args) {
    System.out.println(findSource(MyClass.class));
    // OR
    System.out.println(findSource(String.class));
}

public static String findSource(Class<?> clazz) {
    String resourceToSearch = '/' + clazz.getName().replace(".", "/") + ".class";
    java.net.URL location = clazz.getResource(resourceToSearch);
    String sourcePath = location.getPath();
    // Optional, Remove junk
    return sourcePath.replace("file:", "").replace("!" + resourceToSearch, "");
}
0 голосов
/ 08 сентября 2017

Этот код работал для меня:

private static String getJarPath() throws IOException, URISyntaxException {
    File f = new File(LicensingApp.class.getProtectionDomain().().getLocation().toURI());
    String jarPath = f.getCanonicalPath().toString();
    String jarDir = jarPath.substring( 0, jarPath.lastIndexOf( File.separator ));
    return jarDir;
  }
0 голосов
/ 19 мая 2017

Отметим, что это проверено только в Windows, но я думаю, что оно отлично работает в других операционных системах [Linux,MacOs,Solaris]:).


У меня было 2 .jar файлов в том же каталоге. Я хотел из одного .jar файла запустить другой .jar файл, который находится в том же каталоге.

Проблема в том, что при запуске из cmd текущим каталогом является system32.


Предупреждение!

  • Кажется, что приведенное ниже работает очень хорошо во всех тестах, которые я провел с именем папки ;][[;'57f2g34g87-8+9-09!2#@!$%^^&() или ()%&$%^@# это хорошо работает.
  • Я использую ProcessBuilder со следующим:

? ..

//The class from which i called this was the class `Main`
String path = getBasePathForClass(Main.class);
String applicationPath=  new File(path + "application.jar").getAbsolutePath();


System.out.println("Directory Path is : "+applicationPath);

//Your know try catch here
//Mention that sometimes it doesn't work for example with folder `;][[;'57f2g34g87-8+9-09!2#@!$%^^&()` 
ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath);
builder.redirectErrorStream(true);
Process process = builder.start();

//...code

? getBasePathForClass(Class<?> classs)

    /**
     * Returns the absolute path of the current directory in which the given
     * class
     * file is.
     * 
     * @param classs
     * @return The absolute path of the current directory in which the class
     *         file is.
     * @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user]
     */
    public static final String getBasePathForClass(Class<?> classs) {

        // Local variables
        File file;
        String basePath = "";
        boolean failed = false;

        // Let's give a first try
        try {
            file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());

            if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
                basePath = file.getParent();
            } else {
                basePath = file.getPath();
            }
        } catch (URISyntaxException ex) {
            failed = true;
            Logger.getLogger(classs.getName()).log(Level.WARNING,
                    "Cannot firgue out base path for class with way (1): ", ex);
        }

        // The above failed?
        if (failed) {
            try {
                file = new File(classs.getClassLoader().getResource("").toURI().getPath());
                basePath = file.getAbsolutePath();

                // the below is for testing purposes...
                // starts with File.separator?
                // String l = local.replaceFirst("[" + File.separator +
                // "/\\\\]", "")
            } catch (URISyntaxException ex) {
                Logger.getLogger(classs.getName()).log(Level.WARNING,
                        "Cannot firgue out base path for class with way (2): ", ex);
            }
        }

        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbeans
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    }
0 голосов
/ 14 апреля 2011

Этот метод, вызываемый из кода в архиве, возвращает папку, в которой находится файл .jar. Должно работать в Windows или Unix.


  private String getJarFolder() {
    String name = this.getClass().getName().replace('.', '/');
    String s = this.getClass().getResource("/" + name + ".class").toString();
    s = s.replace('/', File.separatorChar);
    s = s.substring(0, s.indexOf(".jar")+4);
    s = s.substring(s.lastIndexOf(':')-1);
    return s.substring(0, s.lastIndexOf(File.separatorChar)+1);
  } 

Получено из кода по адресу: Определите, работает ли из JAR

0 голосов
/ 04 марта 2014

Я пишу на Java 7 и тестирую в Windows 7 с исполняющей средой Oracle и Ubuntu с исполняемой программой с открытым исходным кодом. Это прекрасно работает для этих систем:

Путь к родительскому каталогу любого запущенного файла JAR (при условии, что класс, вызывающий этот код, является прямым потомком самого архива JAR):

try {
    fooDir = new File(this.getClass().getClassLoader().getResource("").toURI());
} catch (URISyntaxException e) {
    //may be sloppy, but don't really need anything here
}
fooDirPath = fooDir.toString(); // converts abstract (absolute) path to a String

Итак, путь к foo.jar будет:

fooPath = fooDirPath + File.separator + "foo.jar";

Опять же, это не проверялось ни на одном Mac или более старой Windows

0 голосов
/ 21 мая 2015

У меня есть другой способ получить местоположение класса String.

URL path = Thread.currentThread().getContextClassLoader().getResource("");
Path p = Paths.get(path.toURI());
String location = p.toString();

Выходная строка будет иметь вид

C:\Users\Administrator\new Workspace\...

Пробелы и другие символы обрабатываются в форме без file:/. Так будет проще в использовании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...