私のコードはJARファイル(foo.jarなど)の中で実行されます。コード内で、実行中のfoo.jarがどのフォルダーにあるかを知る必要があります。
したがって、foo.jarがC:\FOO\
にある場合は、現在の作業ディレクトリに関係なく、そのパスを取得したいと思います。
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
.toURI()).getPath();
"MyClass"をあなたのクラスの名前に置き換えてください。
クラスがファイル以外の場所からロードされた場合、これは明らかに奇妙なことになります。
私にとって最良の解決策:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
これはスペースと特殊文字に関する問題を解決するはずです。
特定のFile
に対してClass
を取得するには、2つのステップがあります。
Class
をURL
に変換するURL
をFile
に変換する両方のステップを理解し、それらを混同しないことが重要です。
File
を取得したら、getParentFile
を呼び出して包含フォルダーを取得できます。それが必要な場合は可能です。
Class
からURL
他の回答で説明したように、URL
に関連するClass
を見つけるには2つの主要な方法があります。
URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();
URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");
どちらにも長所と短所があります。
getProtectionDomain
アプローチは、クラスの基本位置(例えば、それを含むJARファイル)を得る。ただし、getProtectionDomain()
を呼び出すときにJavaランタイムのセキュリティポリシーがSecurityException
をスローする可能性があるため、アプリケーションをさまざまな環境で実行する必要がある場合は、それらすべてでテストするのが最善です。
getResource
アプローチは、クラスのフルURLリソースパスを生成します。そこから追加の文字列操作を実行する必要があります。それはfile:
パスかもしれませんが、OSGiフレームワーク内で実行する場合はjar:file:
あるいはbundleresource://346.fwk2106232034:4/foo/Bar.class
のようなもっと厄介なこともあります。逆に、getProtectionDomain
のアプローチでは、OSGi内からでもfile:
のURLが正しく生成されます。
クラスがJARファイル内にある場合、getResource("")
とgetResource(".")
の両方が私のテストで失敗したことに注意してください。両方の呼び出しでnullが返されました。安全であると思われるので、私は代わりに上記の#2呼び出しをお勧めします。
URL
からFile
いずれにしても、URL
を取得したら、次のステップはFile
への変換です。これはそれ自身の挑戦です。詳細については、 Kohsuke Kawaguchiさんのブログ投稿 を参照してください。つまり、URLが完全に整形式であれば、new File(url.toURI())
を使用できます。
最後に、URLDecoder
を使うことを 強くお勧めしません 。 URLの一部の文字、特に:
および/
は、有効なURLエンコード文字ではありません。 URLDecoder / Javadocから:
エンコードされた文字列内のすべての文字は、 "a"から "z"、 "A"から "Z"、 "0"から "9"、および " - "、 "_"、 "のいずれかです。 "と" * "。文字 "%"は使用できますが、特殊なエスケープシーケンスの開始として解釈されます。
...
このデコーダが違法な文字列を扱うことができる2つの可能な方法があります。不正な文字だけを残すことも、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 ライブラリにあります。
また使用することができます:
CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();
現在のクラスのURLを見つけるには、ClassLoader.getResource()を使用してください。
例えば:
package foo;
public class Test
{
public static void main(String[] args)
{
ClassLoader loader = Test.class.getClassLoader();
System.out.println(loader.getResource("foo/Test.class"));
}
}
(この例は からの類似の質問 からの抜粋です。)
ディレクトリを見つけるには、URLを手動で分解する必要があります。 jar URLの形式については JarClassLoaderチュートリアル を参照してください。
最近誰も Path
を使うことを提案していないのを見て驚いています。 「Path
クラスには、パスに関する情報の取得、パスの要素へのアクセス、パスの他の形式への変換、またはパスの一部の抽出に使用できるさまざまなメソッドが含まれています 」
したがって、良い代替案はPath
オブジェクトを次のようにすることです。
Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
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();
}
これは他のコメントへのアップグレードです。
.jarファイルの外側(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"));
私は同じ問題を抱えていました、そして私はそれをそのように解決しました:
File currentJavaJarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String currentJavaJarFilePath = currentJavaJarFile.getAbsolutePath();
String currentRootDirectoryPath = currentJavaJarFilePath.replace(currentJavaJarFile.getName(), "");
私はあなたの助けになれば幸いです。
実行中のjarファイルのパスを取得するために、私は上記の解決策を研究し、お互いにいくつかの違いが存在するすべての方法を試してみました。これらのコードがEclipse IDEで実行されている場合、それらはすべて指定されたクラスを含むファイルのパスを見つけて、見つけられたパスで示されたファイルを開くか作成することができるはずです。
しかし、実行可能なjarファイルを直接またはコマンドラインから実行すると、注意が必要です。上記の方法で取得したjarファイルのパスは、jarファイル内に内部パスを指定するため、失敗することになります。として
rsrc:project-name(おそらくメインクラスファイルのパッケージ名 - 指定されたクラスだと言うべきです)
Rsrc:...パスを外部パスに変換することはできません。つまり、Eclipse IDEの外部でjarファイルを実行すると、jarファイルのパスを取得できません。
Eclipseの外部でjarファイルを実行するパスを取得する唯一の方法は、[IDEです。
System.getProperty("Java.class.path")
このコード行は、実行中のjarファイルの生存パス(ファイル名を含む)を返す場合があります(戻りパスは作業ディレクトリではないことに注意してください)。Java文書や一部の人々は、すべてのクラスファイルのパスを返す同じディレクトリにありますが、同じディレクトリにたくさんのjarファイルが含まれている場合のテストでは、実行中のjarのパスのみが返されます(実際にはEclipseで発生した複数パスの問題について)。
gnomeデスクトップ環境から(スクリプトや端末からではなく)クリックしてjarを実行した場合、上記の選択された答えは機能しません。
代わりに、私は以下の解決策が至るところで働いているのが好きです:
try {
return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
}
最も簡単な解決策は、jarを実行するときにパスを引数として渡すことです。
これはシェルスクリプト(Windowsでは.bat、それ以外の場所では.sh)を使って自動化できます。
Java -jar my-jar.jar .
現在の作業ディレクトリを渡すために.
を使用しました。
_アップデート_
ユーザーが誤ってクリックしないように、jarファイルをサブディレクトリに固定することをお勧めします。あなたのコードは、コマンドライン引数が与えられていることを確かめるためにチェックし、引数が欠けているなら良いエラーメッセージを提供するべきです。
私がやっと実用的な(そして短い)解決策を見つける前に、私はたくさんいじらなければなりませんでした。jarLocation
にfile:\
やjar:file\
のような接頭辞が付いている可能性がありますが、これらはString#substring()
を使用して削除できます。
URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
String jarLocation = new File(jarLocationUrl.toString()).getParent();
実際にはこれがより良いバージョンです - フォルダ名にスペースがある場合、古いバージョンは失敗しました。
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についてはあまり知りませんが、ローカルファイルを処理するためにアプリをダウンロードすることは不可能かもしれません。
他の回答は、ディレクトリではないJarファイルの場所であるコードソースを指しているようです。
つかいます
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();
String path = getClass().getResource("").getPath();
パスは常にjarファイル内のリソースを参照します。
私はを使用してjarの実行パスを取得しようとしました
String folder = MyClassName.class.getProtectionDomain().getCodeSource().getLocation().getPath();
c:\ app> Java -jar application.jar
Windowsでフォルダー " c:\ app "の "application.jar"という名前のjarアプリケーションを実行すると、ストリング変数 "folder"の値は " \c:\ app\application"でした。 .jar "パスの正当性をテストするのに問題がありました
File test = new File(folder);
if(file.isDirectory() && file.canRead()) { //always false }
そこで私は "test"を次のように定義しようとしました。
String fold= new File(folder).getParentFile().getPath()
File test = new File(fold);
" \c:\ app\application.jar "の代わりに " c:\ app "のような正しい形式でパスを取得すると、うまくいくことがわかりました。
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上でうまく動作する
他の人についてはよくわかりませんが、私の場合は "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");
イライラしているのは、Eclipseで開発しているときにMyClass.class.getProtectionDomain().getCodeSource().getLocation()
が素晴らしい/bin
ディレクトリを返すことですが、jarにコンパイルすると、パスに不正なファイル名が含まれる/myjarname.jar
部分が含まれることです。
コードが理想の中で動作するようにするために、そしてそれが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");
}
いくつかの解決策を試してみましたが、実行可能なjarファイルがEclipseの "Packaging external libraries"でエクスポートされている(おそらく特別な)ケースに対して正しい結果が得られませんでした。何らかの理由でProtectionDomainに基づくすべての解決策はその場合nullになります。
上記のいくつかのソリューションを組み合わせることで、私は次のような作業コードを達成することができました。
String surroundingJar = null;
// gets the path to the jar file if it exists; or the "bin" directory if calling from Eclipse
String jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).getAbsolutePath();
// gets the "bin" directory if calling from Eclipse or the name of the .jar file alone (without its path)
String jarFileFromSys = System.getProperty("Java.class.path").split(";")[0];
// If both are equal that means it is running from an IDE like Eclipse
if (jarFileFromSys.equals(jarDir))
{
System.out.println("RUNNING FROM IDE!");
// The path to the jar is the "bin" directory in that case because there is no actual .jar file.
surroundingJar = jarDir;
}
else
{
// Combining the path and the name of the .jar file to achieve the final result
surroundingJar = jarDir + jarFileFromSys.substring(1);
}
System.out.println("JAR File: " + surroundingJar);
アーカイブ内のコードから呼び出されるこのメソッドは、.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 path = new File("").getAbsolutePath();
これはWindows
でのみチェックされますが、他のオペレーティングシステムでも完璧に動作すると思います[Linux,MacOs,Solaris
] :)。
同じディレクトリに 2 .jar
ファイルがありました。 1つの.jar
ファイルから、同じディレクトリーにあるもう1つの.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;
}
このコードは私にとって役に立ちました:
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;
}