GCC вставляет инструкцию «ret» в этом случае, в то время как clang pastes «ud2» и приложение вылетают во время выполнения.
Не совсем уверен в других, но в моем случае он не работал с «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");
Лучшее решение для меня:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
Это должно решить проблему с пробелами и специальными символами.
URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
) в Linux. Однако я не пробовал Windows.
– ubuntudroid
3 April 2012 в 12:35
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");
}
Или вы можете передать текущий поток таким образом:
String myPath = Thread.currentThread().getContextClassLoader().getResource("filename").getPath();
На самом деле, это лучшая версия - старая ошибка не удалась, если в имени папки было пробел.
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, но для обработки локальных файлов может не получиться скачать приложение. ?
У меня была та же проблема, и я решил так:
File currentJavaJarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String currentJavaJarFilePath = currentJavaJarFile.getAbsolutePath();
String currentRootDirectoryPath = currentJavaJarFilePath.replace(currentJavaJarFile.getName(), "");
Надеюсь, что я вам помог.
String path = getClass().getResource("").getPath();
Путь всегда ссылается на ресурс в файле jar.
getResource("")
, и getResource(".")
потерпели неудачу в моих тестах, когда класс находился в JAR-файле; оба вызова возвращены null.
– ctrueden
4 December 2012 в 18:50
Чтобы получить File
для данного Class
, есть два шага:
Class
в URL
URL
на File
Важно понимать оба шага и не сдерживать их.
После того, как вы File
, вы можете позвонить getParentFile
, чтобы получить содержащую папку, если это то, что вам нужно.
Class
- URL
Как обсуждалось в других ответах, есть два основных способы найти URL
, относящиеся к Class
.
URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();
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, показанный выше, поскольку это кажется более безопасным.
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 :
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
Единственное решение, которое работает для меня в 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();
}
Вы также можете использовать:
CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();
Другие ответы, похоже, указывают на источник кода, который является расположением файла Jar, который не является каталогом.
Используйте
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();
Упомяните, что он проверен только в Windows
, но я думаю, что он отлично работает на других операционных системах [Linux,MacOs,Solaris
]:).
У меня было 2 .jar
файла в тот же каталог. Я хотел от одного файла .jar
запустить другой файл .jar
, который находится в том же каталоге.
Проблема в том, что при запуске из cmd
текущий каталог system32
].
Предупреждения!
blockquote>
- Ниже показано, что все работает хорошо во всех тестах, которые я сделал даже с именем папки
;][[;'57f2g34g87-8+9-09!2#@!$%^^&()
или()%&$%^@#
он работает хорошо.- Я использую
ProcessBuilder
следующим образом:
Мне пришлось много возиться до того, как я наконец нашел рабочее (и короткое) решение. Возможно, что jarLocation
поставляется с префиксом, подобным file:\
или jar:file\
, который можно удалить с помощью String#substring()
.
URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
String jarLocation = new File(jarLocationUrl.toString()).getParent();
Этот код работал для меня:
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;
}
выбранный ответ выше не работает, если вы запустите банку, щелкнув по нему из среды рабочего стола Gnome (не из какого-либо скрипта или терминала).
Вместо этого я очень рад, что работает следующее решение везде:
try {
return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
}
URLDecoder
для декодирования специальных символов. В частности, символы, подобные +
, будут ошибочно декодированы в пробелы. См. Мой ответ для деталей.
– ctrueden
30 October 2012 в 20:09
Я удивлен, увидев, что никто в последнее время не предложил использовать Path
. Здесь следует цитата: « Класс Path
включает в себя различные методы, которые могут использоваться для получения информации о пути, элементах доступа к пути, преобразования пути к другим формам или извлечения частей пути "
Таким образом, хорошей альтернативой является получение объекта Path
как:
Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
Самое простое решение - передать путь в качестве аргумента при запуске jar.
Вы можете автоматизировать это с помощью сценария оболочки (.bat в Windows, .sh в другом месте):
java -jar my-jar.jar .
Я использовал .
для передачи текущего рабочего каталога.
UPDATE
Возможно, вы захотите вставить файл jar в подкаталог, t случайно щелкните по нему. Ваш код также должен проверить, чтобы убедиться, что аргументы командной строки были предоставлены, и предоставить хорошее сообщение об ошибке, если аргументы отсутствуют.
Этот метод, вызванный из кода в архиве, возвращает папку, в которой находится файл .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
У меня есть другой способ получить расположение String класса.
URL path = Thread.currentThread().getContextClassLoader().getResource("");
Path p = Paths.get(path.toURI());
String location = p.toString();
Строка вывода будет иметь вид
C:\Users\Administrator\new Workspace\...
Пространства и другие символы обрабатывается и в форме без file:/
. Так будет проще использовать.
Игнорировать ответ резервного помощника, он может выглядеть нормально, но имеет несколько проблем:
здесь оба должны быть +1 не -1:
name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');
Очень опасно, потому что не сразу видно, если путь не имеет белых пробелов, но замена только «%» оставит вас с пучком по 20 в каждом белом пространстве:
name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');
Есть лучшие способы, чем этот цикл для белого пробелы.
Также это вызовет проблемы во время отладки.
Этот один лайнер работает для папок, содержащих пробелы или специальные символы (например, ç или õ). Исходный вопрос задает абсолютный путь (рабочий каталог) без самого файла JAR. Протестировано здесь с Java7 на Windows7:
String workingDir = System.getProperty("user.dir");
Ссылка: http://www.mkyong.com/java/how-to-get-the-current-working-directory-in -java /
Чтобы получить путь к запуску файла 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 (о проблемах с несколькими путями, действительно, это произошло в Затмение).
java.class.path
может быть многозначным. Один i> эти значения обязательно предоставят каталог или JAR-файл, где находится текущий класс, но какой?
– user207421
16 December 2016 в 01:06
Я пишу в 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
Я попытался получить пробег в 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 ", и я заметил, что он работает.
Подход 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, "");
}
Вот обновление до других комментариев, которые мне кажутся неполными для специфики
, используя относительную «папку» вне файла .jar (в том же месте):
blockquote>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"));
URLDecoder
для декодирования специальных символов. В частности, символы, подобные +
, будут ошибочно декодированы в пробелы. См. Мой ответ для деталей.
– ctrueden
30 October 2012 в 20:09
URLDecoder
, несмотря на его имя, предназначен для декодирования URL-адресов и имен и значений параметров параметров, а не для URL-адресов.
– user207421
16 December 2016 в 01:05
toURI()
необходим, чтобы избежать проблем со специальными символами, включая пробелы и плюсы. Правильный однострочный:return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI());
ИспользованиеURLDecoder
не работает для многих специальных символов. См. Мой ответ ниже для получения дополнительной информации. – ctrueden 21 November 2012 в 22:25java -Duser.dir=TotallyDiffDir -cp [myjarpath] [myappclasspath]
: «user.dir» устанавливает текущий рабочий каталог, и этот ответ возвращает, где код находится в пути к классам – Raymond Naseef 10 November 2017 в 22:33