रनिंग JAR फ़ाइल का मार्ग कैसे प्राप्त करें?


580

मेरा कोड एक JAR फ़ाइल के अंदर चलता है, foo.jar कहते हैं , और मुझे कोड में, जो foo.jar चल रहा है, फ़ोल्डर में पता होना चाहिए।

इसलिए, अगर foo.jar अंदर है , तो C:\FOO\मैं उस रास्ते को प्राप्त करना चाहता हूं चाहे मेरी वर्तमान कार्यशील निर्देशिका कोई भी हो।


एक समाधान के लिए फैब का जवाब देखें जो काम करता है जब पथ में रिक्त स्थान शामिल होते हैं। यह भी ध्यान दें कि नीचे दिए गए कुछ उत्तर शीर्षक (जार पथ) में प्रश्न को संबोधित करते हैं, कुछ स्वयं प्रश्न (फ़ोल्डर युक्त जार का पथ) को संबोधित करते हैं, और कुछ जार फ़ाइल के अंदर कक्षाओं को पथ प्रदान करते हैं।
एंडी थॉमस

32
ANT में उपयोग करते समय सावधान रहें! ============== मैं स्ट्रिंग पथ को कहता हूं = SomeClass.class.getProtectionDomain ()। GetCodeSource ()। GetLocation ()। GetPath (); और प्राप्त करें: /C:/apache-ant-1.7.1/lib/ant.jar बहुत उपयोगी नहीं है!
डिनो फैंसेलु

दिलचस्प। मूल कोड जिसमें मैंने इसका उपयोग किया था, वह कभी चींटी में नहीं चलाया गया था, इसलिए यह मेरे लिए कोई समस्या नहीं है।
थियागो

2
@ डिनो फैंसेलु, मैंने बिल्कुल वही अनुभव किया जो आपने वर्णित किया है। देव के दौरान काम करता है, जब जार के लिए बनाया विफल रहता है।
बडी

जवाबों:


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

"MyClass" को अपनी कक्षा के नाम से बदलें।

जाहिर है, अगर आपकी कक्षा गैर-फ़ाइल स्थान से लोड की गई थी, तो यह अजीब बातें करेगा।


42
toURI()कदम रिक्त स्थान और प्लस सहित विशेष वर्ण, के साथ से बचने की समस्याओं के लिए महत्वपूर्ण है। सही वन-लाइनर है: return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()); उपयोग करना URLDecoderकई विशेष वर्णों के लिए काम नहीं करता है। अधिक जानकारी के लिए नीचे मेरा उत्तर देखें।
ctrueden

4
नोट: यह jar फ़ाइल के नाम सहित पथ को लौटाता है
Buddy

8
क्या यह रनिंग डायरेक्टरी के बजाय जार फ़ाइल की ओर इशारा नहीं करता है? इस कार्य के लिए आपको परिणाम getParentFile () पर करना होगा।
FOO

1
इसके अलावा, getProtectionDomainयदि आप अपनी कक्षा को स्ट्रेक्ट्रेस से प्राप्त कर रहे हैं तो अशक्त हैं:val strace = Thread.currentThread().getStackTrace; val path = strace(1).getClass.getProtectionDomain
bbarker

1
जावा 8 तक इस पद्धति का उपयोग करना; इस विधि को एक वर्ग में रखना जो बाहरी जार में है, वर्ग-पथ के माध्यम से लोड किया गया है, फिर वास्तविक जार के बजाय बाहरी जार का मार्ग दिया जाएगा।
Mr00Anderson

189

मेरे लिए सबसे अच्छा समाधान:

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

यह रिक्त स्थान और विशेष पात्रों के साथ समस्या को हल करना चाहिए।


8
एक और ध्यान दें: जार से इस फ़ंक्शन को कॉल करते समय, जार का नाम मेरे लिए अंत में जोड़ा गया है, इसलिए निष्पादित करना पड़ा: path.substring (0, path.lastIndexOf ("/") + 1);
15:24 पर 824

11
/ आवश्यक रूप से पथ विभाजक नहीं है। आपको करना चाहिए (नई फ़ाइल (पथ))। getParentFile ()। GetPath () के बजाय।
pjz

10
JAR फ़ाइल नाम के साथ कोई समस्या यहाँ जोड़ा नहीं जा रहा है। URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");लिनक्स पर @Iviggiani one ( ) के साथ संयोजन में UTF रूपांतरण सही समाधान प्रतीत होता है । हालाँकि, मैंने विंडोज पर कोशिश नहीं की।
ubuntudroid

2
धन्यवाद, इसने मुझे लिनक्स और विंडोज दोनों में FileInputStream के साथ अपने JAR की बाहरी फ़ाइलों को लोड करने की अनुमति दी। बस फाइलनाम के सामने डिकोडपथ को जोड़ना था ...
जियोर्जियो

11
खबरदार: URLDecoderविशेष वर्णों को डीकोड करने के लिए उपयोग करने की अनुशंसा नहीं की जाती है । विशेष रूप से, जैसे वर्णों +को गलत तरीके से रिक्त स्थान पर डिकोड किया जाएगा। विवरण के लिए मेरा उत्तर देखें।
ctrueden

153

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 फ़ाइल) के आधार स्थान अर्जित करता है। हालांकि, यह संभव है कि जावा रनटाइम की सुरक्षा नीति SecurityExceptionकॉल करते समय फेंक देगी getProtectionDomain(), इसलिए यदि आपके एप्लिकेशन को विभिन्न प्रकार के वातावरण में चलाने की आवश्यकता है, तो उन सभी में परीक्षण करना सबसे अच्छा है।

getResourceदृष्टिकोण वर्ग, जिसमें से आप अतिरिक्त स्ट्रिंग हेरफेर करने की आवश्यकता होगी के पूर्ण URL संसाधन पथ अर्जित करता है। यह एक file:रास्ता हो सकता है , लेकिन यह OSGi ढांचे के भीतर निष्पादित करते समय jar:file:कुछ नास्टियर भी हो सकता है bundleresource://346.fwk2106232034:4/foo/Bar.class। इसके विपरीत, getProtectionDomainदृष्टिकोण सही ढंग file:से OSGi से भी एक URL देता है।

ध्यान दें कि दोनों getResource("")और getResource(".")मेरे परीक्षण में विफल रहा है, जब वर्ग एक जार फ़ाइल के भीतर बसता; दोनों आह्वान शून्य हो गए। इसलिए मैं इसके बजाय ऊपर दिखाए गए # 2 आह्वान की सलाह देता हूं, क्योंकि यह अधिक सुरक्षित लगता है।

चरण 2: URLसेFile

किसी भी तरह से, एक बार आपके पास URL, अगला चरण एक में बदल जाता है File। यह इसकी अपनी चुनौती है; देख इसके बारे में Kohsuke कावागुची के ब्लॉग पोस्ट पूर्ण विवरण के लिए, लेकिन संक्षेप में, आप उपयोग कर सकते हैं new File(url.toURI())जब तक कि पूरी तरह से यूआरएल अच्छी तरह से ही बना है।

अंत में, मैं अत्यधिक उपयोग को हतोत्साहित करूंगा URLDecoder। URL के कुछ वर्ण :और /विशेष रूप से, मान्य URL-एन्कोड किए गए वर्ण नहीं हैं। से URLDecoder जावाडोक:

यह माना जाता है कि एन्कोडेड स्ट्रिंग के सभी वर्ण निम्न में से एक हैं: "a" "z", "A" के माध्यम से "Z", "0" के माध्यम से "9", और "-", "_", " ।", तथा "*"। चरित्र "%" की अनुमति है, लेकिन एक विशेष बच गए अनुक्रम की शुरुआत के रूप में व्याख्या की गई है।

...

ऐसे दो संभावित तरीके हैं जिनसे यह डिकोडर अवैध तारों से निपट सकता है। यह या तो अवैध चरित्रों को अकेला छोड़ सकता है या यह एक अवैध अवैध व्यापार को फेंक सकता है। जो डिकोडर लेता है वह कार्यान्वयन के लिए छोड़ दिया जाता है।

व्यवहार में, 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 के लिए सही अंकन का उपयोग करके पथ को लौटाएगा। (उदाहरण के लिए विंडोज़)।
बाथशीबा

सुरक्षा के बारे में, मेरा मानना ​​है कि मैंने पाया कि जावा वेबस्टार्ट ने इसकी अनुमति नहीं दी।
थोरबजोरन रावन एंडर्सन

55

आप भी उपयोग कर सकते हैं:

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

3
यह मेरे लिए बेहतर काम करता है, क्योंकि यह जार का रास्ता देता है, वर्ग का नहीं!
T30

मेरे लिए भी काम किया। फैब के जवाब के साथ गठबंधन करें और यह बेहतर हो!
डैनियल्सन ने जूनियर जूनियर

25

अपनी वर्तमान कक्षा के लिए 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 को मैन्युअल रूप से अलग करना होगा। जार URL के प्रारूप के लिए JarClassLoader ट्यूटोरियल देखें ।


मेरी JAR फ़ाइल बाधित है, इसलिए यह उत्तर मेरी समस्या का समाधान नहीं करता है। लेकिन मैंने उस प्रश्न में निर्दिष्ट नहीं किया है, इसलिए यह अभी भी एक वैध उत्तर है।
थियागो

12
यदि यह बाधित है, तो Test.class.getName () का उपयोग करें और उचित मूंगिंग करें।
जॉन स्कीट

1
@JonSkeet आपके उत्तर के साथ बहुत सारी समस्याएं हैं: 1. कोई NPEऐसा नहीं होगा क्योंकि आपने उस प्रश्न पर उत्तर नहीं दिया था जो पूछा गया था (JAR dir का पथ पूछा गया था और आपने बिल्कुल अलग प्रश्न पर उत्तर दिया था: कक्षा के लिए पथ)। 2. जैसा कि दूसरों ने बताया, और मुझे एक ही मुद्दा मिला, यह एप्लेट्स के लिए काम नहीं करता है। 3. लौटाया गया पथ सब पर विहित पथ प्रतिनिधित्व के नहीं है: jar:file:/listener/build/libs/listener-1.0.0-all.jar!/shared/Test.class
व्हाइटएंगल

1
@WhiteAngel: 1) मेरी पोस्ट की अंतिम पंक्ति बताती है कि आपको URL देखने की जरूरत है और इसके अलावा जार फ़ाइल प्राप्त करना होगा। मैं मानता हूं कि यह सबसे पूर्ण उत्तर नहीं है, लेकिन मुझे नहीं लगता कि इसके बारे में बहस करने लायक होने के लिए वास्तव में इतना बुरा है (विशेष रूप से 10 साल बाद ...) 2) Applets यहाँ किसी भी टिप्पणी में उल्लेख नहीं किया गया - अजीब तरह से, मैं डॉन मेरे पास उन सवालों के सभी उत्तरों पर सभी टिप्पणियों को देखने का समय है जो मुझे उत्तर देने के लिए हुआ था। 3) फिर, मैं जार URL के प्रारूप से जुड़ा हुआ हूं।
जॉन स्कीट

2
@WhiteAngel: क्या यह मेरे द्वारा लिखा गया सबसे अच्छा जवाब है? नहीं। क्या यह उतना ही बुरा है जितना कि आप इसे होने के लिए तैयार कर रहे हैं? नहीं, मुझे ऐसा नहीं लगता। (विशेष रूप से आपके द्वारा किए गए दावों के संदर्भ में, एक एनपीई को फेंकना, जो यह नहीं करता है।) मैं आपको इस बारे में एक उपद्रव करने के बजाय अपना खुद का उत्तर जोड़ने का सुझाव दूंगा। यह अधिक सकारात्मक दृष्टिकोण होगा।
जॉन स्कीट

19

मुझे यह देखकर आश्चर्य हुआ कि हाल ही में किसी ने भी उपयोग करने का प्रस्ताव नहीं दिया है Path। यहाँ एक प्रशस्ति पत्र इस प्रकार है: " वर्ग के लिए विभिन्न तरीकों कि पथ के बारे में जानकारी प्राप्त करने के लिए इस्तेमाल किया जा सकता, पथ का उपयोग कर सकते तत्व शामिल हैं, अन्य रूपों, या एक पथ के उद्धरण भागों के लिए पथ परिवर्तित "Path

इस प्रकार, एक अच्छा विकल्प इस प्रकार है Path:

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

3
एक नोट के रूप में, पथ जावा 7.
क्रिस फॉरेन्स

15

एकमात्र समाधान जो मेरे लिए लिनक्स, मैक और विंडोज पर काम करता है:

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

यह काम नहीं करेगा। यदि लिनक्स पर, टूरी () विधि अपवाद को फेंक देगी, और आप लिनक्स के लिए दूसरे हिस्से में नहीं पहुंचेंगे।
विल्हेम सोरबन

9

मुझे भी यही समस्या थी और मैंने इसे इस तरह हल किया:

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

मुझे आशा है कि मैं आपकी मदद कर रहा था।


ऐसा मत करो। URL.getPath () फ़ाइल नाम वापस नहीं करता है और यह बहुत सी परिस्थितियों में विफल हो जाएगा, जैसे कि उन में रिक्त स्थान के साथ फ़ाइल पथ।
वीजीआर

9

यहां अन्य टिप्पणियों के लिए अपग्रेड किया गया है, जो कि मुझे विशेष के लिए अधूरा लगता है

एक रिश्तेदार "फ़ोल्डर" का उपयोग करके .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

फ़ाइल नामों में विशेष वर्णों का उपयोग करने की अनुशंसा नहीं की जाती है।
ज़ोन

URLDecoderअपने नाम के बावजूद, URL को डिकोड करने के लिए है और पैरामीटर नाम और मान बनाते हैं, URL नहीं।
लोरेन का

6

जार फ़ाइल चलाने का मार्ग प्राप्त करने के लिए मैंने उपरोक्त समाधानों का अध्ययन किया है और उन सभी तरीकों की कोशिश की है जो एक दूसरे में कुछ अंतर रखते हैं। यदि ये कोड ग्रहण आईडीई में चल रहे हैं, तो वे सभी संकेतित वर्ग सहित फ़ाइल का मार्ग खोजने में सक्षम होने चाहिए और पाए गए पथ के साथ एक संकेतित फ़ाइल को खोलें या बनाएं।

लेकिन यह मुश्किल है, जब रन करने योग्य जार फ़ाइल को सीधे या कमांड लाइन के माध्यम से चलाया जाता है, तो यह विफल हो जाएगा क्योंकि उपरोक्त विधियों से प्राप्त जार फ़ाइल का मार्ग जार फ़ाइल में एक आंतरिक पथ देगा, अर्थात यह हमेशा एक पथ देता है जैसा

rsrc: प्रोजेक्ट-नाम (शायद मुझे कहना चाहिए कि यह मुख्य वर्ग फ़ाइल का पैकेज नाम है - संकेतित वर्ग)

मैं rsrc को परिवर्तित नहीं कर सकता: ... बाहरी पथ को पथ, जब कि ग्रहण IDE के बाहर जार फ़ाइल को चलाया जाता है तो उसे jar फ़ाइल का पथ नहीं मिल सकता है।

ग्रहण आईडीई के बाहर जार फ़ाइल चलाने का मार्ग प्राप्त करने का एकमात्र संभव तरीका है

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

यह कोड लाइन चल रहे जार फ़ाइल के जीवित पथ (फ़ाइल नाम सहित) को वापस कर सकती है (ध्यान दें कि रिटर्न पथ कार्यशील निर्देशिका नहीं है), क्योंकि जावा दस्तावेज़ और कुछ लोगों ने कहा कि यह सभी वर्ग फ़ाइलों के पथ को वापस कर देगा उसी निर्देशिका में, लेकिन मेरे परीक्षणों के रूप में यदि उसी निर्देशिका में कई जार फाइलें शामिल हैं, तो यह केवल रनिंग जार (कई रास्तों के मुद्दे के बारे में वास्तव में ग्रहण में हुई) का पथ लौटाता है।


java.class.pathबहुविकल्पी हो सकता है। उन मूल्यों में से एक निश्चित रूप से निर्देशिका या JAR फ़ाइल प्रदान करेगा जहां वर्तमान वर्ग स्थित है, लेकिन कौन सा?
लोरेन का

मैं पुष्टि करता हूं, मैंने अन्य समाधानों की कोशिश की, लेकिन कभी भी जार का नाम नहीं मिला। यह बहुत सरलता से काम करता है! धन्यवाद - +1
गिलौड जीरोड-विटोचकिना

5

अन्य उत्तर कोड स्रोत को इंगित करते हैं जो जार फ़ाइल स्थान है जो एक निर्देशिका नहीं है।

उपयोग

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

यह एक निर्देशिका हो सकती है, यदि आप अपनी कक्षाओं को एक JAR फ़ाइल के बजाय एक फाइलसिस्टम से लोड कर रहे हैं, जैसे डीबगिंग करते समय।
लोरेन का

4

यदि आप अपने डेस्कटॉप को Gnome डेस्कटॉप वातावरण (किसी स्क्रिप्ट या टर्मिनल से नहीं) से क्लिक करके चलाते हैं, तो उपरोक्त चयनित उत्तर काम नहीं कर रहा है।

इसके बजाय, मुझे लगता है कि निम्नलिखित समाधान हर जगह काम कर रहा है:

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

2
क्या आपने एक एप्लेट, या एक ऐप में कोशिश की थी। जावा वेब स्टार्ट का उपयोग करके लॉन्च किया गया मेरी समझ यह है कि यह दोनों स्थितियों में विफल हो जाएगा (भले ही ऐप पर भरोसा हो)।
एंड्रयू थॉम्पसन

यह समाधान केवल "का स्थान" लौटा सकता है। भीतर JAR फ़ाइल, स्थान नहीं की JAR फ़ाइल।
लोर्ने

खबरदार: URLDecoderविशेष वर्णों को डीकोड करने के लिए उपयोग करने की अनुशंसा नहीं की जाती है । विशेष रूप से, जैसे वर्णों +को गलत तरीके से रिक्त स्थान पर डिकोड किया जाएगा। विवरण के लिए मेरा उत्तर देखें।
ctrueden

स्प्रिंग बूट में, यह फेंक देगाNullPointerException
रवि पारेख

यदि आपके पास NPEJAR में संसाधन नहीं हैं तो आपके पास होगा ।
व्हाइटएंगल

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

मैंने जार रनिंग पथ का उपयोग करने की कोशिश की

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

c: \ app> java -jar application.jar

"Application.jar" नाम के जार एप्लिकेशन को चलाने पर, फ़ोल्डर " c: \ app " में विंडोज़ पर , स्ट्रिंग चर "फ़ोल्डर" का मूल्य " \ 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 " जैसे एक सही प्रारूप में पथ पाने के लिए और मैंने देखा कि यह काम करता है।


3

जार को चलाते समय सबसे सरल उपाय एक तर्क के रूप में मार्ग को पास करना है।

आप इसे शेल स्क्रिप्ट (विंडोज में .bat, कहीं भी और कहीं भी) के साथ स्वचालित कर सकते हैं:

java -jar my-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();

पथ हमेशा जार फ़ाइल के भीतर संसाधन को संदर्भित करता है।


1
वह पथ स्ट्रिंग अभी भी आपकी आवश्यकता को सरल बनाने की आवश्यकता है। String path = new File(getClass().getResource("").getPath()).getParentFile().getParent(); File jarDir = new File(path.substring(5));
ZZZ

4
दोनों getResource("")और getResource(".")मेरे परीक्षणों में विफल रहे, जब वर्ग एक जार फ़ाइल के भीतर रहता था; दोनों आह्वान शून्य हो गए।
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;}

विंडोज पर अच्छा काम करता है


1

निराशा की बात यह है कि जब आप ग्रहण में विकसित हो रहे होते हैं तो MyClass.class.getProtectionDomain().getCodeSource().getLocation()वह /binनिर्देशिका वापस लौट आती है जो महान होती है, लेकिन जब आप इसे एक जार में संकलित करते हैं, तो पथ में शामिल होता है:/myjarname.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

वास्तव में दूसरों के बारे में निश्चित नहीं है, लेकिन मेरे मामले में यह "रन करने योग्य जार" के साथ काम नहीं करता था और मैंने इसे 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

वहाँ समाधान के कई की कोशिश की है, लेकिन कोई भी (शायद विशेष) मामले के लिए सही परिणाम निकले कि चल जार "निर्यात बाहरी पुस्तकालयों" के साथ ग्रहण में निर्यात किया गया है। किसी कारण से प्रोटेक्शनडोमेन पर आधारित सभी समाधान उस स्थिति में अशक्त हो जाते हैं।

ऊपर दिए गए कुछ समाधानों के संयोजन से मैं निम्नलिखित कार्य कोड प्राप्त करने में कामयाब रहा:

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

1

इसे इस्तेमाल करे:

String path = new File("").getAbsolutePath();

0

यह विधि, जिसे संग्रह में कोड से कहा जाता है, उस फ़ोल्डर को लौटा देती है जहाँ .jar फ़ाइल होती है। यह विंडोज या यूनिक्स में काम करना चाहिए।


  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
"इसे विंडोज या यूनिक्स में काम करना चाहिए।" लेकिन किसी भी एप्लेट और हर ऐप में विफल रहेगा। JWS का उपयोग करके लॉन्च किया गया।
एंड्रयू थॉम्पसन

0

उल्लेख है कि यह केवल में जाँच की है, Windowsलेकिन मुझे लगता है कि यह अन्य ऑपरेटिंग सिस्टम [ Linux,MacOs,Solaris] :) पर सही काम करता है ।


मेरे पास एक ही डायरेक्टरी में 2 .jar फाइलें थीं । मैं एक .jarफ़ाइल से दूसरी .jarफ़ाइल शुरू करना चाहता था जो उसी निर्देशिका में है।

समस्या यह है कि जब आप इसे cmdचालू निर्देशिका से शुरू करते हैं system32


चेतावनी!

  • नीचे सभी परीक्षण में बहुत अच्छी तरह से काम करने लगता है मैंने फ़ोल्डर नाम के साथ भी किया है ;][[;'57f2g34g87-8+9-09!2#@!$%^^&()या()%&$%^@# यह अच्छी तरह से काम करता है।
  • मैं ProcessBuilderनिम्नलिखित के साथ नीचे के साथ उपयोग कर रहा हूं :

🍂 ..

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


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

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

//...code

🍂 getBasePathForClass(Class<?> classs):

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

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

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

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

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

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

        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbeans
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    }

0

इस कोड ने मेरे लिए काम किया:

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

अगर मुझे इस पद्धति का उपयोग करने के लिए 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कार्यान्वयन का उपयोग करते हुए स्प्रिंग बूट एप्लिकेशन के साथ काम करने वाला मेरा पूरा कोड , यह सुनिश्चित करने के लिए कि एप्लिकेशन को हमेशा एक कंसोल दृश्य के भीतर निष्पादित किया जाए (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

मैं जावा 7 में लिखता हूं, और ओरेकल के रनटाइम के साथ विंडोज 7 में परीक्षण करता हूं, और ओपन सोर्स रनटाइम के साथ उबंटू। यह उन प्रणालियों के लिए एकदम सही काम करता है:

किसी भी चालू जार फ़ाइल की मूल निर्देशिका के लिए पथ (इस कोड को कॉल करने वाले वर्ग को जार संग्रह का एक सीधा बच्चा है):

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

फिर, यह किसी भी मैक या पुराने विंडोज पर परीक्षण नहीं किया गया था


-1

getProtectionDomainदृष्टिकोण कभी कभी काम नहीं कर सकते जैसे आप कोर जावा वर्गों से कुछ के लिए जार खोजने के लिए जब (जैसे मेरे मामले में StringBuilderआईबीएम 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, "");
}

URL.getPath () वह नहीं करता है जो आप सोचते हैं कि यह करता है। कोई विशेष वर्ण प्रतिशत-एन्कोडेड होगा।
वीजीआर

-1

मेरे पास एक कक्षा का स्ट्रिंग स्थान प्राप्त करने का एक और तरीका है।

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

आउटपुट स्ट्रिंग का रूप होगा

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

रिक्त स्थान और अन्य वर्ण संभाले हुए हैं, और बिना रूप में file:/। तो उपयोग करने में आसान हो जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.