फ़ाइल के रूप में जावा संसाधन


122

क्या जावा में क्लास लोडर के माध्यम से जार से प्राप्त संसाधन पर फ़ाइल उदाहरण का निर्माण करने का एक तरीका है?

मेरा एप्लिकेशन जार (डिफॉल्ट) या रनटाइम (उपयोगकर्ता इनपुट) में निर्दिष्ट फाइलसिस्टम निर्देशिका से कुछ फाइलों का उपयोग करता है। मैं
इन फ़ाइलों को एक स्ट्रीम
b के रूप में लोड करने के लिए) के लगातार तरीके की तलाश कर रहा हूं ) क्रमशः उपयोगकर्ता-निर्धारित निर्देशिका या जार में निर्देशिका में फ़ाइलों को सूचीबद्ध करना।

संपादित करें: जाहिरा तौर पर, आदर्श दृष्टिकोण java.io से दूर रहना होगा। पूरी तरह से। क्या क्लासपैथ से एक निर्देशिका को लोड करने और इसकी सामग्री (इसमें निहित फाइलें / संस्थाएं) सूचीबद्ध करने का कोई तरीका है?

जवाबों:


58

ClassLoader.getResourceAsStreamऔर Class.getResourceAsStreamनिश्चित रूप से संसाधन डेटा लोड करने के लिए जाने का तरीका है। हालांकि, मुझे विश्वास नहीं है कि क्लासपैथ के एक तत्व की "लिस्टिंग" का कोई तरीका है।

कुछ मामलों में यह असंभव हो सकता है - उदाहरण के लिए, फ्लाई पर डेटा उत्पन्न ClassLoader कर सकता है , यह किस संसाधन के नाम पर आधारित है। यदि आप ClassLoaderएपीआई को देखते हैं (जो मूल रूप से क्लासपैथ तंत्र के माध्यम से काम करता है) तो आप देखेंगे कि आप जो चाहते हैं वह करने के लिए कुछ भी नहीं है।

यदि आप जानते हैं कि आपको वास्तव में जार फ़ाइल मिल गई है, तो आप यह ZipInputStreamपता लगाने के लिए कि क्या उपलब्ध है , उसे लोड कर सकते हैं। इसका मतलब होगा कि आपके पास निर्देशिका और जार फ़ाइलों के लिए अलग-अलग कोड होंगे।

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


3
मैं मानता हूं कि यह कष्टप्रद है - लेकिन यह अन्य तरीकों से क्लासलीडर को अधिक व्यापक रूप से लागू करता है। उदाहरण के लिए, "वेब क्लास लोडर" लिखना आसान है क्योंकि वेब फ़ाइलों को लाने के लिए अच्छा है, लेकिन यह आमतौर पर फाइलों को सूचीबद्ध नहीं करता है ।
जॉन स्कीट

ऐसा लगता है कि यदि आप जिस संसाधन को लोड करने का प्रयास कर रहे हैं, वह 1MiB की तुलना में बहुत बड़ा है, InputStreamतो आप getResourceAsStreamउस आकार के बाद संसाधन के बाइट्स को प्राप्त करने के लिए स्टॉप से ​​प्राप्त करते हैं और इसके बजाय 0 iff इसे जार की तरह संपीड़ित फाइल सिस्टम में समाहित करता है। आप getResourceफ़ाइल को उस स्थिति में स्वतंत्र रूप से उपयोग करने और लोड करने के लिए मजबूर होने लगते हैं ।
mgttlinger

1
@mgttlinger: यह मेरे लिए संभव नहीं लगता है ... शायद एक रिप्रो के साथ एक नया प्रश्न पोस्ट करने के लायक है यदि आप कर सकते हैं।
जॉन स्कीट

यह मुद्दा readविधि के कारण था कि कितना डेटा पढ़ना है (मुझे इस बारे में जानकारी नहीं थी)। और ऐसा लगता है कि पूरी फाइल पढ़ी जा रही है यदि पढ़ी जा रही फाइल एक नियमित फ़ोल्डर में स्थित है। यदि फ़ाइल एक जार के भीतर है क्योंकि इसे पैक किया गया है तो यह इसके कुछ हिस्सों को ही पढ़ता है।
mgttlinger

1
@mgttlinger: नहीं, यह केवल इसके कुछ हिस्सों को नहीं पढ़ेगा - लेकिन यह हर रीड कॉल पर प्रदान किए गए पूरे बफर को नहीं भर सकता है। हमेशा की तरह InputStream, यदि आप पूरे संसाधन को पढ़ना चाहते हैं, तो आपको readरिटर्न -1 तक लूप करना चाहिए ।
जॉन स्कीट

98

मुझे एक ही समस्या थी और निम्नलिखित का उपयोग करने में सक्षम था:

// Load the directory as a resource
URL dir_url = ClassLoader.getSystemResource(dir_path);
// Turn the resource into a File object
File dir = new File(dir_url.toURI());
// List the directory
String files = dir.list()

45
यह दृष्टिकोण क्लासपाथ में
JAR के

1
@ yegor256 यदि आपकी फ़ाइल जार में है तो आप एक FileSystemऑब्जेक्ट बना सकते हैं और उससे प्राप्त कर सकते हैं Path। फिर आप इसे हमेशा की तरह पढ़ सकते हैं। (देखें stackoverflow.com/a/22605905/1876344 )
8

53

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

URL defaultImage = ClassA.class.getResource("/packageA/subPackage/image-name.png");
File imageFile = new File(defaultImage.toURI());

उम्मीद है की वो मदद करदे।


हाँ ist करता है, लेकिन toURI()विफल रहेगा।
ओलिवियर फौचेक्स

10

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

public static File getResourceAsFile(String resourcePath) {
    try {
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
        if (in == null) {
            return null;
        }

        File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
        tempFile.deleteOnExit();

        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            //copy stream
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

4

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

ClassLoader.getResourceAsStream ("some/pkg/resource.properties");

अधिक विधियाँ उपलब्ध हैं, जैसे यहाँ देखें: http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html


आपके प्रतिक्रिया के लिए धन्येवाद। मैं getResourceAsStream के बारे में जानता हूं, लेकिन मुझे नहीं लगता कि मैं उस के माध्यम से classpath से एक निर्देशिका लोड कर सकता हूं।
मंट्राम

जावा निर्देशिका में एक फ़ाइल है (UNIX जड़ें मुझे लगता है) ताकि आपको कम से कम कोशिश करनी चाहिए।
टॉपचेफ

मुझे लगता है कि एक निर्देशिका में फ़ाइलों को सूचीबद्ध करने के लिए आपको java.io.File का उपयोग करने की आवश्यकता है। आप ClassLoader.findResource के साथ फ़ाइलें देख सकते हैं जो एक URL लौटाता है जिसे फ़ाइल में पारित किया जा सकता है।
नाथन वोक्सलैंड

2

यह एक विकल्प है: http://www.uofr.net/~greg/java/get-resource-listing.html


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