मैं अपने जार फ़ाइल के अंदर से एक संसाधन "फ़ोल्डर" कैसे प्राप्त कर सकता हूं?


139

मेरे पास अपनी परियोजना की जड़ में एक संसाधन फ़ोल्डर / पैकेज है, मैं एक निश्चित फ़ाइल लोड नहीं करना चाहता हूं। अगर मैं एक निश्चित फ़ाइल लोड करना चाहता था, तो मैं class.getResourceAsStream का उपयोग करूंगा और मैं ठीक हो जाऊंगा !! मैं वास्तव में क्या करना चाहता हूं, संसाधन फ़ोल्डर के भीतर एक "फ़ोल्डर" लोड करना है, उस फ़ोल्डर के अंदर फ़ाइलों पर लूप और प्रत्येक फ़ाइल के लिए एक स्ट्रीम प्राप्त करें और सामग्री में पढ़ें ... मान लें कि फ़ाइल नाम रनटाइम से पहले निर्धारित नहीं हैं ... मुझे क्या करना चाहिए? क्या आपकी जार फ़ाइल में फ़ोल्डर के अंदर फ़ाइलों की सूची प्राप्त करने का एक तरीका है? ध्यान दें कि संसाधनों के साथ जार फ़ाइल वही जार फ़ाइल है जिसमें से कोड चलाया जा रहा है ...

अग्रिम में धन्यवाद...




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

जवाबों:


111

अंत में, मुझे इसका हल मिला:

final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());

if(jarFile.isFile()) {  // Run with JAR file
    final JarFile jar = new JarFile(jarFile);
    final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
    while(entries.hasMoreElements()) {
        final String name = entries.nextElement().getName();
        if (name.startsWith(path + "/")) { //filter according to the path
            System.out.println(name);
        }
    }
    jar.close();
} else { // Run with IDE
    final URL url = Launcher.class.getResource("/" + path);
    if (url != null) {
        try {
            final File apps = new File(url.toURI());
            for (File app : apps.listFiles()) {
                System.out.println(app);
            }
        } catch (URISyntaxException ex) {
            // never happens
        }
    }
}

जब आप IDE (जार फ़ाइल के साथ नहीं) पर एप्लिकेशन चलाते हैं तो दूसरा ब्लॉक काम करता है, अगर आपको यह पसंद नहीं है तो आप इसे हटा सकते हैं।


सही उत्तर अपडेट करें। हालांकि यह वह नहीं है जो मैं करना चाहता हूं, विशेष रूप से 34000+ स्रोत फ़ाइलों वाले कोड में ... लेकिन यह एकमात्र समाधान प्रतीत होता है। धन्यवाद।
मुस्तफा ज़िनाली

4
FYI करें, वेबस्टार्ट से लॉन्च होने पर यह काम नहीं करता है क्योंकि getPath सर्वर के डोमेन के सापेक्ष कुछ देता है।
आमोस १

1
लगता है कि यह काम करने जा रहा है अगर रास्ता एक जार में है, तोरी रूपांतरण पर यह त्रुटि देगा: java.lang.IllegalArgumentException: यूआरआई पदानुक्रमित नहीं है
ट्राइब्लॉइड

4
केवल सिंगल-जार फ़ाइल के लिए काम करता है, दूसरे जार में निर्भरता से संसाधनों को निकालने के लिए काम नहीं करता है
ट्रिबब्लॉयड

2
यह एक सुरक्षित समाधान नहीं है, क्योंकि: 1. यह मानता है। एक ही सिस्टम पर .jar फ़ाइल एक स्थानीय फ़ाइल है; 2. URL.getPath () एक मान्य फ़ाइल नाम नहीं लौटाता है, यह केवल URL का पथ भाग देता है, जिसमें सभी प्रतिशत-एस्केप बरकरार हैं; 3. ProtectionDomain.getCodeSource () नल को वापस कर सकता है
वीजीआर

14

निम्नलिखित प्रयास करें। यदि आपका वर्ग पथ com.abc.package.MyClass है तो
संसाधन पथ बनाएं। "<PathRelativeToThisClassFile>/<ResourceDirectory>"और आपकी resoure फाइलें src / com / abc / package / resource / के भीतर हैं:

URL url = MyClass.class.getResource("resources/");
if (url == null) {
     // error - missing folder
} else {
    File dir = new File(url.toURI());
    for (File nextFile : dir.listFiles()) {
        // Do something with nextFile
    }
}

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

URL url = MyClass.class.getResource("/com/abc/package/resources/");

27
समय और प्रयास के लिए धन्यवाद, लेकिन यह काम नहीं करता है जब आपका कोड एक .jar फ़ाइल के भीतर और आपके संसाधन उस .jar फ़ाइल में भी होते हैं। जब आप एक .jar फ़ाइल के अंदर होते हैं, तो आप एक फ़ाइल () नहीं बना सकते हैं और आपको उस फ़ोल्डर के लिए URL भी नहीं मिल सकता है ... मैं व्यक्तिगत रूप से इसके साथ शांति से आया था और प्रत्येक फ़ाइल को XML में सूचीबद्ध किया था ... I don ' टी लगता है कि आप एक जार फ़ाइल के अंदर एक फ़ोल्डर के लिए कर सकते हैं ...
Mostafa Zeinali

2
क्षमा करें कि आपकी समस्याएँ हैं। हालाँकि, यह वास्तव में तब काम करता है जब आपका कोड आधार जार फ़ाइल में होता है और आपके संसाधन भी उस जार फ़ाइल में होते हैं। आपकी डिस्क पर फ़ाइल () नहीं बन रही है - आप जार फ़ाइल में जावा मेमोरी में फ़ाइल पढ़ रहे हैं। ध्यान दें कि ClassLoader डिस्क पर एक निर्देशिका के बराबर जार फ़ाइल के इलाज के लिए काफी खुश है। यहाँ स्रोत से विवरण है:
Glen Best

1
बस एक जार पर कोड चलाया और त्रुटि मिली ... उफ़। वी सॉरी, मेरा बुरा। "फ़ाइल: ...! / Dir1 / dir2 ..." के साथ जार URL पथ को संभालने की आवश्यकता है। दो सुधार: stackoverflow.com/questions/1429172/… या स्ट्रिंग jarPath = dirURL.getPath ()। सबस्ट्रिंग (5, dirURL.getPath ()) indexOf (")"); जरीफाइल जार = नया जरीफाइल (URLDecoder.decode (jarPath, "UTF-8")); एनुमरेशन <JarEntry> प्रविष्टियाँ = jar.entries (); जबकि (प्रविष्टियां .hasMoreElements ()) // // कुछ करें}
Glen Best

3
Javadoc से यह स्पष्ट है कि विधि सभी परिस्थितियों में किसी फ़ाइल को वापस करने की गारंटी नहीं है। लेकिन, अगर आप वास्तव में क्यू को पढ़ते हैं, तो ओपी निर्माण द्वारा फाइलों और फ़ोल्डरों के साथ काम करने की 100% गारंटी है। क्यू निर्देशिका और फ़ाइलों तक पहुंच प्राप्त करने के लिए कह रहा है - यह अधिक विशिष्ट है कि एपीआई के सामान्यीकृत अमूर्तता। आवश्यकता को पूरा करने के लिए फ़ाइल में रूपांतरण उचित और सही है। कृपया इस तरह के विपरीत टिप्पणियों को पोस्ट करने से पहले ठीक से क्यू पढ़ें। चीयर्स।
ग्लेन बेस्ट

7
ओपी फाइलों और निर्देशिकाओं के साथ काम नहीं कर रहा है। वह एक JAR फ़ाइल में संसाधनों के साथ काम कर रहा है। एक JAR फ़ाइल में संसाधन फ़ाइल या निर्देशिका नहीं हैं और उन्हें Fileकक्षा के साथ सूचीबद्ध नहीं किया जा सकता है । यह कोड JAR फ़ाइल के अंदर संसाधनों के साथ काम नहीं करता है। अवधि।
लोर्ने

7

मुझे पता है यह कई साल पहले की बात है। लेकिन सिर्फ अन्य लोगों के लिए इस विषय पर आते हैं। getResourceAsStream()निर्देशिका पथ के साथ विधि का उपयोग करने के लिए आप क्या कर सकते हैं , और इनपुट स्ट्रीम में उस डायर की सभी फाइलें होंगी। उसके बाद आप प्रत्येक फ़ाइल नाम के साथ dir पथ को सम्‍मिलित कर सकते हैं और प्रत्येक फ़ाइल के लिए पाश में getResourceAsStream कॉल कर सकते हैं।


7
जब तक आप चीजों को तोड़-मरोड़ कर पेश नहीं करते, तब तक यह अच्छी तरह से काम करता है।
Tustin2121

1
मुझे लगता है कि यह साफ होने के बाद से स्वीकृत समाधान होना चाहिए और अलग-अलग मामलों में जार और आईडीई संस्करणों को संभालने की आवश्यकता नहीं है। हालांकि मुझे यकीन नहीं है कि getResource फ़ोल्डर नहीं ढूँढ रहा है, लेकिन getResourceAsStream करता है।
रघुराम ओन्ती श्रीनिवासन

6

मुझे हाथों में एक ही समस्या थी जब मैं जार में पैक किए गए संसाधनों से कुछ हडूप विन्यास को लोड करने का प्रयास कर रहा था ... आईडीई और जार (रिलीज़ संस्करण) दोनों पर।

मैंने java.nio.file.DirectoryStreamस्थानीय फाइलसिस्टम और जार दोनों पर निर्देशिका सामग्री पर पुनरावृति करने के लिए सबसे अच्छा काम किया।

String fooFolder = "/foo/folder";
....

ClassLoader classLoader = foofClass.class.getClassLoader();
try {
    uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
    throw new FooException(e.getMessage());
} catch (NullPointerException e){
    throw new FooException(e.getMessage());
}

if(uri == null){
    throw new FooException("something is wrong directory or files missing");
}

/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
    /** jar case */
    try{
        URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
        //jar.toString() begins with file:
        //i want to trim it out...
        Path jarFile = Paths.get(jar.toString().substring("file:".length()));
        FileSystem fs = FileSystems.newFileSystem(jarFile, null);
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
        for(Path p: directoryStream){
            InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
        performFooOverInputStream(is);
        /** your logic here **/
            }
    }catch(IOException e) {
        throw new FooException(e.getMessage());     
    }
}
else{
    /** IDE case */
    Path path = Paths.get(uri);
    try {
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
        for(Path p : directoryStream){
            InputStream is = new FileInputStream(p.toFile());
            performFooOverInputStream(is);
        }
    } catch (IOException _e) {
        throw new FooException(_e.getMessage());
    }
}

इसने मेरे लिए ठीक काम किया। केवल मैंने 'Path jarFile = Paths.get (jar.toString ()। Substring ("फ़ाइल:" लंबाई ())); 'पथ jarFile = Paths.get (jar.toURI ());' विंडोज में काम करने के लिए। FileSystem ऑब्जेक्ट के लिए संसाधन विवरण के साथ एक प्रयास का उपयोग किया।
जारल जैकबसेन

यह मेरे लिए काम किया! मैं docker में dropwizard एप्लिकेशन चला रहा था।
nIKUNJ

4

निम्न कोड पाथ के रूप में "फ़ोल्डर" लौटाता है, भले ही वह जार के अंदर हो या न हो।

  private Path getFolderPath() throws URISyntaxException, IOException {
    URI uri = getClass().getClassLoader().getResource("folder").toURI();
    if ("jar".equals(uri.getScheme())) {
      FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
      return fileSystem.getPath("path/to/folder/inside/jar");
    } else {
      return Paths.get(uri);
    }
  }

जावा 7+ की आवश्यकता है।


अच्छा! मुझे हालांकि जोड़ना है, कि फाइलसिस्टम क्लोजेबल है, जिसका मतलब है कि आपको इसे कुछ बिंदुओं पर सिस्टम सिस्टम से मुक्त करना होगा। बेशक, लौटा पथ उसके तुरंत बाद अमान्य हो जाएगा।
किरिल गमाज़कोव

ध्यान दें कि जार फ़ाइल के मामले में संसाधन का नाम (यहाँ पैकेज + folder) फ़ाइल सिस्टम बनाते समय नजरअंदाज किया जाता है। इसलिए getPathनहीं लौटता folder/path/to/..., लेकिन केवल path/to/...
Marcono1234

1

एक और समाधान, आप इसे ResourceLoaderइस तरह से उपयोग कर सकते हैं :

import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;

@Autowire
private ResourceLoader resourceLoader;

...

Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
    load(fi.next())
}

0

सरल ... OSGi का उपयोग करें। OSGi में आप findEntries और findPaths के साथ अपने बंडल की प्रविष्टियों पर पुनरावृति कर सकते हैं।


10
अगर इसमें OSGI शामिल है, तो मैं शायद ही इसे 'सरल' कहूंगा। लेकिन अगर आप पहले से ही OSGI का उपयोग कर रहे हैं ... हाँ यकीन है। लेकिन इस विशेष समस्या को हल करने के लिए बस OSGI में जाने का सुझाव देना थोड़ा बहुत लगता है।
क्रिस

ओएसजीआई कई अन्य समस्याओं को भी हल करता है और आजकल इसे शुरू करना बहुत आसान है। OSGi enRoute ट्यूटोरियल देखें
पीटर

मैं OSGi से तब तक दूर रहूँगा जब तक कि आपको पहले से ही इसका उपयोग करने की आवश्यकता न हो। 90 के दशक के IMO की तैनाती की समस्याओं को हल करने वाले ब्लोटवेयर को डिजाइन किया गया।
user2337270

-1

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

URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);

URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);

URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

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

-1

जैसा कि अन्य उत्तर बताते हैं, एक बार जब संसाधन जार फ़ाइल के अंदर होते हैं, तो चीजें वास्तव में बदसूरत हो जाती हैं। हमारे मामले में, यह समाधान:

https://stackoverflow.com/a/13227570/516188

परीक्षणों में बहुत अच्छी तरह से काम करता है (क्योंकि जब परीक्षण चलाए जाते हैं तो कोड एक जार फ़ाइल में पैक नहीं किया जाता है), लेकिन जब ऐप वास्तव में सामान्य रूप से चलता है तो काम नहीं करता है। तो मैंने जो किया है वह है ... मैं एप्लिकेशन में फ़ाइलों की सूची को हार्डकोड करता हूं, लेकिन मेरे पास एक परीक्षण है जो डिस्क से वास्तविक सूची पढ़ता है (यह परीक्षण के बाद से काम कर सकता है) और विफल हो जाता है यदि वास्तविक सूची नहीं है ऐप के रिटर्न की सूची के साथ टी मैच।

इस तरह मेरे ऐप में सरल कोड है (कोई ट्रिक्स नहीं), और मुझे यकीन है कि मैं परीक्षण के लिए धन्यवाद सूची में एक नई प्रविष्टि जोड़ना नहीं भूलूंगा।


-25

यह लिंक आपको बताता है कि कैसे।

जादू getResourceAsStream () विधि है:

InputStream is = 
this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml")

20
नही यार!! मुझे एक भी फाइल नहीं चाहिए !! मुझे एक पूरा फ़ोल्डर चाहिए, जिसकी उप-फाइलें पूर्व-निर्धारित समय से पूर्व-निर्धारित हैं !!!
मुस्तफा ज़ाइनीली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.