実行中のJARファイルのパスを取得する方法は?


580

私のコードはfoo.jarなどのJARファイル内で実行されます。コードでは、実行中のfoo.jarがどのフォルダーにあるかを知る必要があります。

したがって、foo.jarがにある場合C:\FOO\、現在の作業ディレクトリが何であっても、そのパスを取得したいと思います。


パスにスペースが含まれている場合に機能する解決策については、Fabの回答を参照してください。また、以下のいくつかの回答は、タイトル(jarパス)内の質問に対応し、いくつかは質問自体(jarを含むフォルダーのパス)に対応し、いくつかはjarファイル内のクラスへのパスを提供します。
アンディトーマス

32
ANTで使用する場合は注意してください。==============私は文字列を呼び出しますpath = SomeClass.class.getProtectionDomain()。getCodeSource()。getLocation()。getPath(); /C:/apache-ant-1.7.1/lib/ant.jarはあまり役に立ちません。
Dino Fancellu 2012年

面白い。私がこれを使用した元のコードはantで実行されなかったので、私にとっては問題ではありません。
チアゴチャベス

2
@Dino Fancellu、私はあなたが説明したとおりに体験しました。開発中に動作し、jarにビルドすると失敗します。
バディ

回答:


539
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
    .toURI()).getPath();

「MyClass」をクラスの名前に置き換えます。

明らかに、クラスがファイル以外の場所からロードされた場合、これは奇妙なことをします。


43
このtoURI()手順は、スペースやプラスなどの特殊文字の問題を回避するために不可欠です。正しいワンライナーは次のとおりです。return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()); 使用URLDecoderは、多くの特殊文字では機能しません。詳細については、以下の私の回答を参照してください。
ctrueden

4
注:これは、jarファイルの名前を含むパスを返します
Buddy

8
これは、実行中のディレクトリではなく、jarファイルを指していませんか?この作業では、結果のgetParentFile()を実行する必要があります。
FOO

1
また、getProtectionDomainあなたがstracktraceからクラスを取得している場合はnullです:val strace = Thread.currentThread().getStackTrace; val path = strace(1).getClass.getProtectionDomain
bbarker

1
このメソッドをJava 8まで使用します。このメソッドを、クラスパスを介してロードされた外部Jar内のクラスに配置すると、実際に実行中のJarではなく、外部jarのパスが指定されます。
Mr00Anderson

189

私にとっての最善の解決策:

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

これにより、スペースと特殊文字の問題が解決されます。


8
もう1つ注意:JARからこの関数を呼び出すと、jarの名前が最後に追加されるため、実行する必要がありました。path.substring(0、path.lastIndexOf( "/")+ 1);
will824

11
/は必ずしもパス区切り文字ではありません。代わりに(new File(path))。getParentFile()。getPath()を実行する必要があります。
pjz 2012年

10
ここにJARファイル名を追加しても問題ありません。URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");Linux での@Iviggianiの()と組み合わせると、UTF変換は完璧なソリューションのようです。しかし、私はWindowsで試しませんでした。
ubuntudroid

2
ありがとうございます。これにより、LinuxとWindowsの両方で、FileInputStreamを使用してJARの外部にあるファイルをロードできました。ファイル名の前にdecodedpathを追加するだけでした...
giorgio79

11
注意:URLDecoder特殊文字のデコードに使用することはお勧めしません。特に、などの文字+は誤ってスペースにデコードされます。詳細については、私の回答を参照してください。
ctrueden 2012年

153

File特定ののを取得するには、Class2つのステップがあります。

  1. Classをaに変換しますURL
  2. URLをaに変換しますFile

両方のステップを理解し、それらを混同しないことが重要です。

あなたがしたらFile、あなたは呼び出すことができますgetParentFileそれはあなたが必要なものであれば、入っているフォルダを取得します。

ステップ1:ClassURL

他の回答で説明されているように、にURL関連するものを見つけるには2つの主要な方法があります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:パスかもしれませんが、OSG​​iフレームワーク内で実行するときのjar:file:ようにbundleresource://346.fwk2106232034:4/foo/Bar.class、あるいはもっとひどいものになるかもしれません。逆に、このgetProtectionDomainアプローチはfile:OSGi内からでもURLを正しく生成します。

クラスがJARファイル内にある場合、テストで失敗したことgetResource("")getResource(".")失敗したことに注意してください。どちらの呼び出しもnullを返しました。したがって、安全だと思われるため、代わりに上記の#2呼び出しをお勧めします。

ステップ2:URLFile

どちらの方法でも、を取得したらURL、次のステップはへの変換Fileです。これはそれ自体が課題です。詳細については、河口浩介氏のブログ投稿を参照してください。つまり、new File(url.toURI())URLが完全に整形式である限り使用できます。

最後に、を使用しないことを強くお勧め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共通ライブラリにあります。


5
+1; これまでのベストアンサー:OSの正しい表記を使用してパスを返します。(例:Windowsの場合は\)。
バトシェバ2013

セキュリティに関しては、Java WebStartではこれが許可されていないことがわかりました。
するThorbjörnRavnアンデルセン

55

次のものも使用できます。

CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();

3
これは私にとってはうまくいきます。クラスではなくジャーのパスを提供するからです。
T30 2014年

私も働いた。ファブの答えと組み合わせると、より良くなります!
Danielson

25

ClassLoader.getResource()を使用して、現在のクラスのURLを見つけます。

例えば:

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チュートリアルを参照してください。


私のJARファイルは難読化されているため、この回答では問題が解決しません。しかし、私はそれを質問で指定しなかったので、これはまだ有効な答えです。
チアゴチャベス

12
難読化されている場合は、Test.class.getName()を使用して、適切な変更を行います。
Jon Skeet、

1
@JonSkeetあなたの答えには非常に多くの問題があります:1. NPE尋ねられた質問に答えなかったのでありません(JAR dirへのパスが尋ねられ、まったく異なる質問に答えました:クラスへのパス)。2.他の人が指摘したように、同じ問題が発生しましたが、アプレットでは機能しません。3.返されたパスは、正規のパス表現ではありません:jar:file:/listener/build/libs/listener-1.0.0-all.jar!/shared/Test.class
WhiteAngel 2018年

1
@WhiteAngel:1)私の投稿の最後の行は、jarファイルを取得するために、URLを確認し、それを個別に選択する必要があることを示しています。私はそれが最も完全な答えではないことに同意しますが、議論する価値があることは本当にそれほど悪くないと思います(特に10年後...)2)アプレットはここのコメント言及されていません-不思議なことに、私はしません私がたまたま回答を投稿した質問について、すべての回答に対するすべてのコメントを見る時間はありません。3)繰り返しますが、私はjar URLのフォーマットにリンクしています。
Jon Skeet

2
@WhiteAngel:これまでに書いた中で最高の答えですか?いいえ。あなたがそうであるようにそれを作っているのと同じくらい悪いですか?いいえ、そうは思いません。(特に、あなたがNPEを投げてその周りで行った主張に関しては、そうではありません。)これについて大騒ぎするのではなく、あなた自身の答えを追加することをお勧めします。それはより積極的なアプローチでしょう。
Jon Skeet、2018年

19

最近使用を提案したものがないことに驚いていますPath。「:ここで引用する以下のクラスは、パスに関する情報を取得するために使用することができる種々の方法、経路のアクセス要素を含む、他の形態のパスを変換する、またはパスの抽出部Path

したがって、次のようにPathオブジェクトを取得することをお勧めします。

Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());

3
注意点としては、パスは、Java 7で利用可能な出発である
クリスForrence

15

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

これは機能しません。Linuxの場合、toUri()メソッドは例外をスローし、Linuxのelse部分には到達しません。
Wilhelm Sorban

9

私は同じ問題を抱えていて、それをそのように解決しました:

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

お役に立てば幸いです。


それをしないでください。URL.getPath()ファイル名を返さ、スペースを含むファイルパスなど、多くの状況で失敗します。
VGR

9

ここに他のコメントへのアップグレードがあります。

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

4
注意:URLDecoder特殊文字のデコードに使用することはお勧めしません。特に、などの文字+は誤ってスペースにデコードされます。詳細については、私の回答を参照してください。
ctrueden 2012年

ファイル名に特殊文字を使用することはお勧めしません。
Zon

URLDecoderは、その名前にもかかわらず、URLおよびフォームパラメータの名前と値をデコードするためのものであり、URLではありません。
ローン侯爵

6

実行中のjarファイルのパスを取得するために、上記の解決策を研究し、互いに多少の違いがあるすべての方法を試しました。これらのコードがEclipse IDEで実行されている場合、それらはすべて、示されたクラスを含むファイルのパスを見つけ、見つかったパスで示されたファイルを開くか作成できるはずです。

しかし、それはトリッキーです、実行可能なjarファイルを直接またはコマンドラインから実行すると、上記のメソッドから取得したjarファイルのパスがjarファイルの内部パスを提供するため、失敗します。つまり、常にパスを提供します。なので

rsrc:project-name(メインクラスファイルのパッケージ名-指定されたクラスであると言えるかもしれません)

rsrc:...パスを外部パスに変換できません。つまり、Eclipse IDEの外部でjarファイルを実行すると、jarファイルのパスを取得できません。

Eclipse IDEの外部で実行中のjarファイルのパスを取得する唯一の可能な方法は、

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

このコード行は、実行中のjarファイルの生きているパス(ファイル名を含む)を返す可能性があります(戻りパスは作業ディレクトリではないことに注意してください)。Javaドキュメントと一部の人々は、すべてのクラスファイルのパスを返すと述べています同じディレクトリにありますが、同じディレクトリに多くのjarファイルが含まれている場合のテストでは、実行中のjarのパスのみが返されます(実際にEclipseで発生した複数パスの問題について)。


java.class.path複数の値を持つことができます。これらの値の1つは、確かに現在のクラスが配置されているディレクトリまたはJARファイルを提供しますが、どれを指定しますか?
ローン侯爵

確認しました。他の解決策を試しましたが、jarファイル名を取得できませんでした。これは非常に簡単に機能します。感謝-+1
ギヨームgirod-vitouchkina 2017

5

他の回答は、ディレクトリではないJARファイルの場所であるコードソースをポイントしているようです。

使用する

return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();

デバッグ時など、JARファイルではなくファイルシステムからクラスをロードする場合は、ディレクトリにすることもできます。
ローンの侯爵

4

上記の選択した回答は、Gnomeデスクトップ環境(スクリプトや端末からではなく)からクリックしてjarを実行する場合は機能しません。

代わりに、私は次の解決策がどこでも機能しているのが好きです:

    try {
        return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return "";
    }

2
アプレットまたはアプリでそれを試しましたか。Java Web Startを使用して起動しましたか?私の理解では、両方の状況で失敗します(アプリが信頼されている場合でも)。
Andrew Thompson

このソリューションは、「。」の場所のみを返すことができます。内の JARファイルではなく、場所 JARファイル。
ローンの侯爵

注意:URLDecoder特殊文字のデコードに使用することはお勧めしません。特に、などの文字+は誤ってスペースにデコードされます。詳細については、私の回答を参照してください。
ctrueden 2012年

春のブーツでは、それがスローされますNullPointerException
Ravi Parekh

あなたは持っていますNPE何のリソースがJARに存在しない場合。
WhiteAngel 2018年

3

実際には、これはより良いバージョンです-フォルダ名にスペースが含まれている場合、古いバージョンは失敗しました。

  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

を使用してjar実行パスを取得しようとしました

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

c:\ app> java -jar application.jar

「application.jar」という名前のjarアプリケーションをWindowsの「c:\ app」フォルダーで実行すると、文字列変数「folder」の値は「\ 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 \ application.jar」ではなく c:\ app」の。


3

最も簡単な解決策は、jarの実行時にパスを引数として渡すことです。

これは、シェルスクリプト(Windowsでは.bat、その他の場所では.sh)を使用して自動化できます。

java -jar my-jar.jar .

使った .は現在の作業ディレクトリを渡していました。

更新

jarファイルをサブディレクトリに貼り付けて、ユーザーが誤ってクリックしないようにすることができます。コードでは、コマンドライン引数が指定されていることを確認し、引数がない場合は適切なエラーメッセージを提供する必要もあります。


3

私は最終的に実用的な(そして短い)解決策を見つける前に、多くのことをいじらなければなりませんでした。
またはのjarLocationような接頭辞がに付属し ている可能性があります。これはを使用して削除できます。file:\jar:file\String#substring()

URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
String jarLocation = new File(jarLocationUrl.toString()).getParent();

2
String path = getClass().getResource("").getPath();

パスは常にjarファイル内のリソースを参照します。


1
このパス文字列は、必要に応じて単純化する必要があります。String path = new File(getClass().getResource("").getPath()).getParentFile().getParent(); File jarDir = new File(path.substring(5));
ZZZ 2010年

4
クラスがJARファイル内にある場合、テストgetResource("")と両方でgetResource(".")失敗しました。どちらの呼び出しもnullを返しました。
ctrueden

2
これがスローされNullPointerExceptionます。
ローン侯爵

2
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でうまく動作します


1

イライラするのは、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");
}

1

他の人についてはよくわかりませんが、私の場合、「実行可能な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");

1

いくつかの解決策を試してみましたが、実行可能jarがEclipseの「外部ライブラリのパッケージ化」でエクスポートされた(おそらく特別な)場合に正しい結果が得られませんでした。何らかの理由で、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);


0

このメソッドは、アーカイブ内のコードから呼び出され、.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から実行するかどうかを決定


3
「WindowsでもUnixでも動作するはずです。」しかし、すべてのアプレットとすべてのアプリで失敗します。JWSを使用して起動されます。
Andrew Thompson

0

チェックインのみであるWindowsが、他のオペレーティングシステムでも完璧に機能すると思います[ Linux,MacOs,Solaris] :)。


私が持っていた2つの .jar、同じディレクトリ内のファイルを。1つの.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

このコードは私のために働きました:

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

このコードは、プログラムがJARファイルまたはIDE内で実行されているかどうかを確認するのに役立ちました。

private static boolean isRunningOverJar() {
    try {
        String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();

        if (pathJar.toLowerCase().contains(".jar")) {
            return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        return false;
    }
}

WindowsのJARファイルの完全パスを取得する必要がある場合、次の方法を使用しています。

    private static String getPathJar() {
        try {
            final URI jarUriPath =
                    Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
            String jarStringPath = jarUriPath.toString().replace("jar:", "");
            String jarCleanPath  = Paths.get(new URI(jarStringPath)).toString();

            if (jarCleanPath.toLowerCase().contains(".jar")) {
                return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
            } else {
                return null;
            }
        } catch (Exception e) {
            log.error("Error getting JAR path.", e);
            return null;
        }
    }

CommandLineRunner実装を使用してSpring Bootアプリケーションを処理する私の完全なコードは、アプリケーションが常にコンソールビュー内で実行されるようにする(JARファイル名を誤ってダブルクリックする)ために、次のコードを使用しています。

@SpringBootApplication
public class Application implements CommandLineRunner {
    public static void main(String[] args) throws IOException {
        Console console = System.console();

        if (console == null && !GraphicsEnvironment.isHeadless() && isRunningOverJar()) {
            Runtime.getRuntime().exec(new String[]{"cmd", "/c", "start", "cmd", "/k",
                    "java -jar \"" + getPathJar() + "\""});
        } else {
            SpringApplication.run(Application.class, args);
        }
    }

    @Override
    public void run(String... args) {
        /*
        Additional code here...
        */
    }

    private static boolean isRunningOverJar() {
        try {
            String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();

            if (pathJar.toLowerCase().contains(".jar")) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    private static String getPathJar() {
        try {
            final URI jarUriPath =
                    Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
            String jarStringPath = jarUriPath.toString().replace("jar:", "");
            String jarCleanPath  = Paths.get(new URI(jarStringPath)).toString();

            if (jarCleanPath.toLowerCase().contains(".jar")) {
                return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }
}

-1

私はJava 7で記述し、Oracleのランタイムを使用してWindows 7でテストし、オープンソースのランタイムを使用して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

getProtectionDomainいくつかのコアJavaクラス(たとえば、私の場合StringBuilderはIBM JDK内のクラス)のjarを見つける必要がある場合など、このアプローチが機能しない場合がありますが、以下はシームレスに機能します。

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, "");
}

URL.getPath()は、思ったようには動作しません。特殊文字はパーセントでエンコードされます。
VGR 2016年

-1

クラスの文字列の場所を取得する別の方法があります。

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

出力文字列は次の形式になります

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

スペースやその他の文字は、なしの形式で処理されfile:/ます。だから使いやすくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.