Java. Как убедиться, что сгенерированный файл находится рядом с .jar [duplicate]

GCC вставляет инструкцию «ret» в этом случае, в то время как clang pastes «ud2» и приложение вылетают во время выполнения.

487
задан informatik01 29 October 2013 в 07:44
поделиться

27 ответов

Не совсем уверен в других, но в моем случае он не работал с «Runnable jar», и я получил его, исправляя коды вместе с ответом phchen2, а другой из этой ссылки: Как получить путь работающего файла JAR? Код:

               String path=new java.io.File(Server.class.getProtectionDomain()
                .getCodeSource()
                .getLocation()
                .getPath())
          .getAbsolutePath();
       path=path.substring(0, path.lastIndexOf("."));
       path=path+System.getProperty("java.class.path");
451
ответ дан Community 16 August 2018 в 00:24
поделиться
  • 1
    Мой JAR-файл обфускается, поэтому этот ответ не решает мою проблему. Но я не указал это в вопросе, так что это по-прежнему действительный ответ. – Thiago Chaves 3 June 2009 в 15:43
  • 2
    Если он запутался, используйте Test.class.getName () и выполните соответствующие настройки. – Jon Skeet 3 June 2009 в 15:53
  • 3
    Шаг toURI() необходим, чтобы избежать проблем со специальными символами, включая пробелы и плюсы. Правильный однострочный: return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()); Использование URLDecoder не работает для многих специальных символов. См. Мой ответ ниже для получения дополнительной информации. – ctrueden 21 November 2012 в 22:25
  • 4
    Кажется, что toURI () прерывает пути от общего сетевого ресурса. – Brain2000 24 February 2015 в 00:15
  • 5
    Примечание: это возвращает путь, включающий имя файла jar – E B 2 October 2015 в 11:36
  • 6
    Разве это не указывает на файл jar вместо текущего каталога? Вам нужно будет сделать результат getParentFile () для этой работы. – F.O.O 10 June 2016 в 11:53
  • 7
    @ F.O.O. [A] Да, это указывает на JAR-файл [B] Нет, у него нет отношения к рабочему каталогу. Докажите это, выполнив java -Duser.dir=TotallyDiffDir -cp [myjarpath] [myappclasspath]: «user.dir» устанавливает текущий рабочий каталог, и этот ответ возвращает, где код находится в пути к классам – Raymond Naseef 10 November 2017 в 22:33

Лучшее решение для меня:

String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");

Это должно решить проблему с пробелами и специальными символами.

176
ответ дан adatapost 16 August 2018 в 00:24
поделиться
  • 1
    Еще одно замечание: при вызове этой функции из Jar имя флага добавляется в конец для меня, поэтому ему пришлось выполнить: path.substring (0, path.lastIndexOf (& quot; / & quot;) + 1); – will824 5 October 2011 в 16:29
  • 2
    / не обязательно является разделителем путей. Вы должны сделать (новый файл (путь)). GetParentFile (). GetPath (). – pjz 29 March 2012 в 22:36
  • 3
    Нет проблем с добавлением имени файла JAR. Преобразование UTF, по-видимому, является идеальным решением в сочетании с @Iviggiani one (URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");) в Linux. Однако я не пробовал Windows. – ubuntudroid 3 April 2012 в 12:35
  • 4
    Спасибо, это позволило мне загружать файлы, внешние для моего JAR, с помощью FileInputStream в Linux и Windows. Просто нужно было добавить decodedpath перед именем файла ... – giorgio79 12 May 2012 в 07:49
  • 5
    Остерегайтесь: не рекомендуется использовать URLDecoder для декодирования специальных символов. В частности, символы, подобные +, будут ошибочно декодированы в пробелы. См. Мой ответ для деталей. – ctrueden 30 October 2012 в 20:08

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

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

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");
}
1
ответ дан Alexander 16 August 2018 в 00:24
поделиться

Или вы можете передать текущий поток таким образом:

String myPath = Thread.currentThread().getContextClassLoader().getResource("filename").getPath();
-1
ответ дан Assem BARDI 16 August 2018 в 00:24
поделиться

На самом деле, это лучшая версия - старая ошибка не удалась, если в имени папки было пробел.

  private String getJarFolder() {
    // get name and path
    String name = getClass().getName().replace('.', '/');
    name = getClass().getResource("/" + name + ".class").toString();
    // remove junk
    name = name.substring(0, name.indexOf(".jar"));
    name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');
    // remove escape characters
    String s = "";
    for (int k=0; k<name.length(); k++) {
      s += name.charAt(k);
      if (name.charAt(k) == ' ') k += 2;
    }
    // replace '/' with system separator char
    return s.replace('/', File.separatorChar);
  }

Что касается провала с апплетами, вы обычно не имеете доступа к локальным файлам так или иначе. Я не знаю много о JWS, но для обработки локальных файлов может не получиться скачать приложение. ?

3
ответ дан bacup lad 16 August 2018 в 00:24
поделиться
  • 1
    Существует несколько встроенных способов декодирования пути. Не нужно писать свой собственный код. – user207421 16 December 2016 в 01:04

У меня была та же проблема, и я решил так:

File currentJavaJarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());   
String currentJavaJarFilePath = currentJavaJarFile.getAbsolutePath();
String currentRootDirectoryPath = currentJavaJarFilePath.replace(currentJavaJarFile.getName(), "");

Надеюсь, что я вам помог.

6
ответ дан Charlie 16 August 2018 в 00:24
поделиться
  • 1
    Не делай этого. URL.getPath () не возвращает имя файла, и он не будет работать во многих случаях, таких как пути к файлам с пробелами в них. – VGR 13 June 2016 в 15:32
String path = getClass().getResource("").getPath();

Путь всегда ссылается на ресурс в файле jar.

3
ответ дан CoolBeans 16 August 2018 в 00:24
поделиться
  • 1
    Эта строка пути должна быть упрощена до ваших потребностей. – ZZZ 15 November 2010 в 22:42
  • 2
    String path = new File (getClass (). GetResource (& quot;) & quot; getPath ()). GetParentFile (). GetParent (); Файл jarDir = новый файл (путь.substring (5)); – ZZZ 15 November 2010 в 22:59
  • 3
    И getResource(""), и getResource(".") потерпели неудачу в моих тестах, когда класс находился в JAR-файле; оба вызова возвращены null. – ctrueden 4 December 2012 в 18:50
  • 4
    Это выбрасывает NullPointerException. – user207421 16 December 2016 в 01:06

Чтобы получить File для данного Class, есть два шага:

  1. Преобразуйте Class в URL
  2. Преобразуйте URL на File

Важно понимать оба шага и не сдерживать их.

После того, как вы File, вы можете позвонить getParentFile, чтобы получить содержащую папку, если это то, что вам нужно.

Шаг 1: Class - URL

Как обсуждалось в других ответах, есть два основных способы найти URL, относящиеся к Class.

  1. URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();
  2. URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");

Оба имеют за и против.

Подход getProtectionDomain дает базовое расположение класса (например, содержащий JAR-файл). Однако, возможно, что политика безопасности среды выполнения Java будет вызывать SecurityException при вызове getProtectionDomain(), поэтому, если ваше приложение должно работать в различных средах, лучше всего протестировать их во всех них.

Подход getResource дает полный путь ресурса URL класса, из которого вам потребуется выполнить дополнительные манипуляции с строками. Это может быть путь file:, но также может быть jar:file: или даже что-то более неприятное, чем bundleresource://346.fwk2106232034:4/foo/Bar.class при выполнении в рамках OSGi. И наоборот, подход getProtectionDomain корректно дает URL-адрес file: даже изнутри OSGi.

Обратите внимание, что оба getResource("") и getResource(".") потерпели неудачу в моих тестах, когда класс находился в JAR-файле; оба вызова возвращены null. Таким образом, я рекомендую вместо этого вызов # 2, показанный выше, поскольку это кажется более безопасным.

Шаг 2: URL - File

В любом случае, если у вас есть URL , следующий шаг преобразуется в File. Это его собственная задача; см. сообщение в блоге Kohsuke Kawaguchi об этом , но, в общем, вы можете использовать new File(url.toURI()), пока URL полностью сформирован.

Наконец, я бы сильно обескураживает с помощью URLDecoder. Некоторые символы URL, : и / в частности, являются недопустимыми символами с кодировкой URL. Из URLDecoder Javadoc:

Предполагается, что все символы в кодированной строке являются одним из следующих: «a» через «z», «A» через «Z», «0» - «9» и «-», «_», «.» И «*». Символ «%» разрешен, но интерпретируется как начало специальной экранированной последовательности.

...

Существует два возможных способа, которыми этот декодер может иметь дело с незаконными строками , Он может либо оставить незаконные символы в одиночку, либо он может вызвать исключение IllegalArgumentException. Какой подход принимает декодер, остается реализовать.

На практике URLDecoder обычно не бросает IllegalArgumentException как угрожаемое выше. И если ваш путь к файлу имеет пробелы, закодированные как %20, этот подход может работать. Однако, если в вашем пути к файлу есть другие неалфарические символы, такие как +, у вас будут проблемы с URLDecoder, искажающими ваш путь к файлу.

Рабочий код

Для достижения этих шагов , у вас могут быть следующие методы:

/**
 * Gets the base location of the given class.
 * <p>
 * If the class is directly on the file system (e.g.,
 * "/path/to/my/package/MyClass.class") then it will return the base directory
 * (e.g., "file:/path/to").
 * </p>
 * <p>
 * If the class is within a JAR file (e.g.,
 * "/path/to/my-jar.jar!/my/package/MyClass.class") then it will return the
 * path to the JAR (e.g., "file:/path/to/my-jar.jar").
 * </p>
 *
 * @param c The class whose location is desired.
 * @see FileUtils#urlToFile(URL) to convert the result to a {@link File}.
 */
public static URL getLocation(final Class<?> c) {
    if (c == null) return null; // could not load the class

    // try the easy way first
    try {
        final URL codeSourceLocation =
            c.getProtectionDomain().getCodeSource().getLocation();
        if (codeSourceLocation != null) return codeSourceLocation;
    }
    catch (final SecurityException e) {
        // NB: Cannot access protection domain.
    }
    catch (final NullPointerException e) {
        // NB: Protection domain or code source is null.
    }

    // NB: The easy way failed, so we try the hard way. We ask for the class
    // itself as a resource, then strip the class's path from the URL string,
    // leaving the base path.

    // get the class's raw resource path
    final URL classResource = c.getResource(c.getSimpleName() + ".class");
    if (classResource == null) return null; // cannot find class resource

    final String url = classResource.toString();
    final String suffix = c.getCanonicalName().replace('.', '/') + ".class";
    if (!url.endsWith(suffix)) return null; // weird URL

    // strip the class's path from the URL string
    final String base = url.substring(0, url.length() - suffix.length());

    String path = base;

    // remove the "jar:" prefix and "!/" suffix, if present
    if (path.startsWith("jar:")) path = path.substring(4, path.length() - 2);

    try {
        return new URL(path);
    }
    catch (final MalformedURLException e) {
        e.printStackTrace();
        return null;
    }
} 

/**
 * Converts the given {@link URL} to its corresponding {@link File}.
 * <p>
 * This method is similar to calling {@code new File(url.toURI())} except that
 * it also handles "jar:file:" URLs, returning the path to the JAR file.
 * </p>
 * 
 * @param url The URL to convert.
 * @return A file path suitable for use with e.g. {@link FileInputStream}
 * @throws IllegalArgumentException if the URL does not correspond to a file.
 */
public static File urlToFile(final URL url) {
    return url == null ? null : urlToFile(url.toString());
}

/**
 * Converts the given URL string to its corresponding {@link File}.
 * 
 * @param url The URL to convert.
 * @return A file path suitable for use with e.g. {@link FileInputStream}
 * @throws IllegalArgumentException if the URL does not correspond to a file.
 */
public static File urlToFile(final String url) {
    String path = url;
    if (path.startsWith("jar:")) {
        // remove "jar:" prefix and "!/" suffix
        final int index = path.indexOf("!/");
        path = path.substring(4, index);
    }
    try {
        if (PlatformUtils.isWindows() && path.matches("file:[A-Za-z]:.*")) {
            path = "file:/" + path.substring(5);
        }
        return new File(new URL(path).toURI());
    }
    catch (final MalformedURLException e) {
        // NB: URL is not completely well-formed.
    }
    catch (final URISyntaxException e) {
        // NB: URL is not completely well-formed.
    }
    if (path.startsWith("file:")) {
        // pass through the URL as-is, minus "file:" prefix
        path = path.substring(5);
        return new File(path);
    }
    throw new IllegalArgumentException("Invalid URL: " + url);
}

Эти методы можно найти в библиотеке SciJava Common :

136
ответ дан ctrueden 16 August 2018 в 00:24
поделиться
  • 1
    +1; лучший ответ на сегодняшний день: он вернет путь, используя правильную нотацию для ОС. (например, \ для окон). – Bathsheba 5 September 2013 в 09:47
public static String dir() throws URISyntaxException
{
    URI path=Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
    String name= Main.class.getPackage().getName()+".jar";
    String path2 = path.getRawPath();
    path2=path2.substring(1);

    if (path2.contains(".jar"))
    {
        path2=path2.replace(name, "");
    }
    return path2;}

Хорошо работает в Windows

2
ответ дан Denton 16 August 2018 в 00:24
поделиться

Единственное решение, которое работает для меня в Linux, Mac и Windows:

public static String getJarContainingFolder(Class aclass) throws Exception {
  CodeSource codeSource = aclass.getProtectionDomain().getCodeSource();

  File jarFile;

  if (codeSource.getLocation() != null) {
    jarFile = new File(codeSource.getLocation().toURI());
  }
  else {
    String path = aclass.getResource(aclass.getSimpleName() + ".class").getPath();
    String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
    jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
    jarFile = new File(jarFilePath);
  }
  return jarFile.getParentFile().getAbsolutePath();
}
12
ответ дан Dmitry Trofimov 16 August 2018 в 00:24
поделиться
  • 1
    Это не будет работать. Если в Linux метод toUri () будет генерировать исключение, и вы не достигнете части else, для linux. – Wilhelm Sorban 9 January 2018 в 18:45

Вы также можете использовать:

CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();
44
ответ дан dusan 16 August 2018 в 00:24
поделиться
  • 1
    Это работает лучше для меня, потому что это дает путь Jar, а не класса! – T30 4 March 2014 в 15:44
  • 2
    где я могу это сказать? – kegs Production 17 October 2017 в 07:37

Другие ответы, похоже, указывают на источник кода, который является расположением файла Jar, который не является каталогом.

Используйте

return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();
3
ответ дан F.O.O 16 August 2018 в 00:24
поделиться
  • 1
    Это может быть каталог, если вы загружаете свои классы из файловой системы вместо JAR-файла, например. при отладке. – user207421 16 December 2016 в 01:07
  • 2
    @EJP В вопросе четко указывается JAR-файл. Недостаток голосов недопустим. – F.O.O 18 December 2016 в 19:10

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


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

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


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

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

0
ответ дан GOXR3PLUS 16 August 2018 в 00:24
поделиться

Мне пришлось много возиться до того, как я наконец нашел рабочее (и короткое) решение. Возможно, что jarLocation поставляется с префиксом, подобным file:\ или jar:file\, который можно удалить с помощью String#substring().

URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
String jarLocation = new File(jarLocationUrl.toString()).getParent();
3
ответ дан Jelle 16 August 2018 в 00:24
поделиться

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

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
ответ дан John Lockwood 16 August 2018 в 00:24
поделиться

выбранный ответ выше не работает, если вы запустите банку, щелкнув по нему из среды рабочего стола Gnome (не из какого-либо скрипта или терминала).

Вместо этого я очень рад, что работает следующее решение везде:

    try {
        return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return "";
    }
5
ответ дан lviggiani 16 August 2018 в 00:24
поделиться
  • 1
    Вы попробовали это в апплете или приложении. запущен с использованием Java Web Start? Мое понимание заключается в том, что он потерпит неудачу в обеих ситуациях (даже если приложение доверено). – Andrew Thompson 28 September 2011 в 08:56
  • 2
    Это решение может только возвращать местоположение «.». в файле JAR, а не в каталоге of файла JAR. – user207421 6 March 2012 в 05:11
  • 3
    Остерегайтесь: не рекомендуется использовать URLDecoder для декодирования специальных символов. В частности, символы, подобные +, будут ошибочно декодированы в пробелы. См. Мой ответ для деталей. – ctrueden 30 October 2012 в 20:09
  • 4
    В Spring boot, он будет бросать NullPointerException – Ravi Parekh 20 December 2017 в 07:23

Я удивлен, увидев, что никто в последнее время не предложил использовать Path . Здесь следует цитата: « Класс Path включает в себя различные методы, которые могут использоваться для получения информации о пути, элементах доступа к пути, преобразования пути к другим формам или извлечения частей пути "

Таким образом, хорошей альтернативой является получение объекта Path как:

Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
16
ответ дан mat_boy 16 August 2018 в 00:24
поделиться

Самое простое решение - передать путь в качестве аргумента при запуске jar.

Вы можете автоматизировать это с помощью сценария оболочки (.bat в Windows, .sh в другом месте):

java -jar my-jar.jar .

Я использовал . для передачи текущего рабочего каталога.

UPDATE

Возможно, вы захотите вставить файл jar в подкаталог, t случайно щелкните по нему. Ваш код также должен проверить, чтобы убедиться, что аргументы командной строки были предоставлены, и предоставить хорошее сообщение об ошибке, если аргументы отсутствуют.

3
ответ дан Max Heiber 16 August 2018 в 00:24
поделиться
  • 1
    Это нехорошее решение. Что произойдет, если я отправлю файл jar пользователю (windows), и он просто дважды щелкнет файл, чтобы запустить его? – Vini.g.fer 30 March 2016 в 13:10
  • 2
    @ Vini.g.fer, в моем ответе я написал & quot; Вы можете автоматизировать это с помощью сценария оболочки (.bat в Windows, .sh где-нибудь еще) & quot ;. Пользователи вряд ли смогут щелкнуть банку, если она находится в подкаталоге. В ответ на ваши отзывы я обновил этот вопрос с этой рекомендацией. Я использовал это в производстве с несколькими клиентами, и он работал хорошо. Можете ли вы отказаться от участия? – Max Heiber 30 March 2016 в 19:49
  • 3
    Спасибо за обновление, но, к сожалению, я не являюсь пользователем, который был заблокирован. Если бы я мог повернуть вспять вниз. – Vini.g.fer 31 March 2016 в 02:28
  • 4
    @ Vini.g.fer круто, спасибо за ваши отзывы – Max Heiber 31 March 2016 в 17:14

Этот метод, вызванный из кода в архиве, возвращает папку, в которой находится файл .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
ответ дан n00begon 16 August 2018 в 00:24
поделиться
  • 1
    «Он должен работать либо в Windows, либо в Unix». но не удастся в любом апплете и каждом приложении. запущен с использованием JWS. – Andrew Thompson 14 April 2011 в 20:36

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

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

Строка вывода будет иметь вид

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

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

-1
ответ дан NoSegfault 16 August 2018 в 00:24
поделиться

Игнорировать ответ резервного помощника, он может выглядеть нормально, но имеет несколько проблем:

здесь оба должны быть +1 не -1:

name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');

Очень опасно, потому что не сразу видно, если путь не имеет белых пробелов, но замена только «%» оставит вас с пучком по 20 в каждом белом пространстве:

name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');

Есть лучшие способы, чем этот цикл для белого пробелы.

Также это вызовет проблемы во время отладки.

-1
ответ дан rciafardone 16 August 2018 в 00:24
поделиться

Этот один лайнер работает для папок, содержащих пробелы или специальные символы (например, ç или õ). Исходный вопрос задает абсолютный путь (рабочий каталог) без самого файла JAR. Протестировано здесь с Java7 на Windows7:

String workingDir = System.getProperty("user.dir");

Ссылка: http://www.mkyong.com/java/how-to-get-the-current-working-directory-in -java /

-2
ответ дан Rodrigo N. Hernandez 16 August 2018 в 00:24
поделиться
  • 1
    Это работает по совпадению. Это не работает на OSX для фляги, в комплекте с .app, например. – JoshuaD 2 May 2015 в 20:09
  • 2
    Спасибо JoshuaD за информацию. Если он работает по совпадению, значит, он выглядит как несоблюдение, если вы проверяете официальную документацию. Официальная информация не указывает, что она зависит от ОС. docs.oracle.com/javase/tutorial/essential/environment/… - & gt; «Класс System поддерживает объект« Свойства », который описывает конфигурацию текущей рабочей среды», – Rodrigo N. Hernandez 4 May 2015 в 02:30
  • 3
    В Windows ЕСЛИ вы запускаете jar путем двойного щелчка в проводнике, тогда рабочий каталог является каталогом jar, но на всех системах даже Windows он (очень) легко запускает банку с рабочим каталогом где-то, кроме каталога jar, и это дает неверный ответ. – dave_thompson_085 19 March 2016 в 17:16
  • 4
    Текущий рабочий каталог пользователя не имеет никакого отношения к пути к запущенному файлу JAR. Они могут быть одинаковыми только по совпадению, как указано в @JoshuaD. Здесь нет «несоблюдения». – user207421 16 December 2016 в 01:09

Чтобы получить путь к запуску файла jar, я изучил вышеупомянутые решения и пробовал все методы, которые существуют, некоторые различия друг друга. Если этот код запущен в Eclipse IDE, все они должны иметь возможность найти путь к файлу, включая указанный класс, и открыть или создать указанный файл с найденным путем.

Но это сложно, когда выполняется файл runnable jar напрямую или через командную строку, он будет сбой, так как путь jar-файла, полученного из указанных выше методов, даст внутренний путь в файле jar, то есть он всегда дает путь как

rsrc: имя проекта (возможно, я должен сказать, что это имя пакета основного файла класса - указанный класс)

Я не могу преобразовать путь rsrc: ... к внешнему пути, то есть при запуске файла jar за пределами Eclipse IDE он не может получить путь к файлу jar.

Единственный возможный способ получить путь к запуску файла jar вне Eclipse IDE -

System.getProperty("java.class.path")

эта строка кода может возвращать живой путь (включая имя файла) работающего файла jar (обратите внимание, что путь возврата не является рабочим каталогом), поскольку java-документ и некоторые peop le сказал, что он вернет пути всех файлов классов в том же каталоге, но поскольку мои тесты, если в том же каталоге содержат много файлов jar, он возвращает только путь запуска jar (о проблемах с несколькими путями, действительно, это произошло в Затмение).

5
ответ дан simon 16 August 2018 в 00:24
поделиться
  • 1
    java.class.path может быть многозначным. Один эти значения обязательно предоставят каталог или JAR-файл, где находится текущий класс, но какой? – user207421 16 December 2016 в 01:06
  • 2
    Я подтверждаю, я пробовал другие решения, но никогда не получал имя файла jar. Это работает очень просто! спасибо - +1 – guillaume girod-vitouchkina 16 April 2017 в 10:18

Я пишу в 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

-1
ответ дан sudoBen 16 August 2018 в 00:24
поделиться

Я попытался получить пробег в jar, используя

String folder = MyClassName.class.getProtectionDomain().getCodeSource().getLocation().getPath();

c: \ app> java -jar application.jar

Запуск баночки приложение под названием «application.jar», в Windows в папке « c: \ app », значение переменной «String» было « \ c: \ app \ application.jar ", и у меня были проблемы с проверкой правильности пути

File test = new File(folder);
if(file.isDirectory() && file.canRead()) { //always false }

Поэтому я попытался определить« тест »как:

String fold= new File(folder).getParentFile().getPath()
File test = new File(fold);

, чтобы получить путь в правильном формате например " c: \ app " вместо " \ c: \ app \ application.jar ", и я заметил, что он работает.

2
ответ дан TheGreatPsychoticBunny 16 August 2018 в 00:24
поделиться

Подход getProtectionDomain может не работать иногда, например. когда вам нужно найти банку для некоторых основных классов 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, "");
}
-1
ответ дан Vasu 16 August 2018 в 00:24
поделиться
  • 1
    URL.getPath () не делает то, что, по вашему мнению, делает. Любые специальные символы будут закодированы в процентах. – VGR 13 June 2016 в 15:39

Вот обновление до других комментариев, которые мне кажутся неполными для специфики

, используя относительную «папку» вне файла .jar (в том же месте):

String path = 
  YourMainClassName.class.getProtectionDomain().
  getCodeSource().getLocation().getPath();

path = 
  URLDecoder.decode(
    path, 
    "UTF-8");

BufferedImage img = 
  ImageIO.read(
    new File((
        new File(path).getParentFile().getPath()) +  
        File.separator + 
        "folder" + 
        File.separator + 
        "yourfile.jpg"));
6
ответ дан Zon 16 August 2018 в 00:24
поделиться
  • 1
    Остерегайтесь: не рекомендуется использовать URLDecoder для декодирования специальных символов. В частности, символы, подобные +, будут ошибочно декодированы в пробелы. См. Мой ответ для деталей. – ctrueden 30 October 2012 в 20:09
  • 2
    Использование специальных символов в именах файлов не рекомендуется. – Zon 15 July 2013 в 11:41
  • 3
    URLDecoder, несмотря на его имя, предназначен для декодирования URL-адресов и имен и значений параметров параметров, а не для URL-адресов. – user207421 16 December 2016 в 01:05
Другие вопросы по тегам:

Похожие вопросы: