खोज…


परिचय

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

टिप्पणियों

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

संसाधनों को ClassLoader.getResource और ClassLoader.getResourceAsStream विधियों के साथ एक्सेस किया जा सकता है। सबसे आम उपयोग का मामला संसाधनों को उसी पैकेज में रखा जाना है जो उन्हें पढ़ता है; Class.getResource और Class.getResourceAsStream विधियाँ इस सामान्य उपयोग के मामले की सेवा करती हैं।

एक getResource विधि और getResourceAsStream विधि के बीच एकमात्र अंतर यह है कि पूर्व एक URL लौटाता है, जबकि बाद वाला उस URL को खोलता है और एक InputStream देता है।

ClassLoader के तरीके तर्क के रूप में पथ-प्रकार संसाधन नाम को स्वीकार करते हैं और उस नाम से मेल खाने वाली प्रविष्टि के लिए ClassLoader के Classpath में प्रत्येक स्थान की खोज करते हैं।

  • यदि कोई क्लासपैथ स्थान एक .jar फ़ाइल है, तो निर्दिष्ट नाम के साथ जार प्रविष्टि को एक मैच माना जाता है।
  • यदि कोई क्लासपैथ स्थान एक निर्देशिका है, तो निर्दिष्ट नाम के साथ उस निर्देशिका के अंतर्गत एक रिश्तेदार फ़ाइल को एक मैच माना जाता है।

संसाधन नाम किसी सापेक्ष URL के पथ भाग के समान है। सभी प्लेटफार्मों पर, यह निर्देशिका विभाजकों के रूप में फ़ॉरवर्ड स्लैश ( / ) का उपयोग करता है। यह एक स्लैश से शुरू नहीं होना चाहिए।

कक्षा के संबंधित तरीके समान हैं, सिवाय इसके:

  • संसाधन नाम स्लैश के साथ शुरू हो सकता है, उस स्थिति में जब प्रारंभिक स्लैश को हटा दिया जाता है और शेष नाम ClassLoader की संबंधित विधि को पारित कर दिया जाता है।
  • यदि संसाधन नाम स्लैश से शुरू नहीं होता है, तो इसे उस वर्ग के सापेक्ष माना जाता है जिसका getResource या getResourceAsStream विधि कहा जाता है। वास्तविक संसाधन नाम पैकेज / नाम है, जहां पैकेज पैकेज वर्ग के अंतर्गत आता है जो करने के लिए, प्रत्येक अवधि एक स्लेश द्वारा बदल दिया साथ का नाम है हो जाता है, और नाम विधि को दी मूल तर्क है।

उदाहरण के लिए:

package com.example;

public class ExampleApplication {
    public void readImage()
    throws IOException {

        URL imageURL = ExampleApplication.class.getResource("icon.png");

        // The above statement is identical to:
        // ClassLoader loader = ExampleApplication.class.getClassLoader();
        // URL imageURL = loader.getResource("com/example/icon.png");

        Image image = ImageIO.read(imageURL);
    }
}

संसाधनों को नामांकित पैकेजों में रखा जाना चाहिए, बल्कि एक .jar फ़ाइल की जड़ में, उसी कारण वर्गों को पैकेजों में रखा गया है: कई विक्रेताओं के बीच टकराव को रोकने के लिए। उदाहरण के लिए, यदि एकाधिक .jar फाइलें क्लासपाथ में हैं, और उनमें से एक में इसके रूट में एक config.properties प्रविष्टि है, getResource पर कॉल करें या getResourceAsStream विधियाँ जो भी। वर्गपथ। यह उन वातावरणों में अनुमान लगाने योग्य व्यवहार नहीं है, जहां क्लासपैथ ऑर्डर एप्लिकेशन के सीधे नियंत्रण में नहीं है, जैसे कि जावा ईई।

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

संसाधन केवल-पढ़े जाते हैं। संसाधन लिखने का कोई तरीका नहीं है। नौसिखिया डेवलपर्स अक्सर यह मानने की गलती करते हैं कि चूंकि आईडीई (जैसे ग्रहण) में विकसित होने के दौरान संसाधन एक अलग भौतिक फ़ाइल है, इसलिए इसे सामान्य मामले में एक अलग भौतिक फ़ाइल की तरह व्यवहार करना सुरक्षित होगा। हालाँकि, यह सही नहीं है; अनुप्रयोगों को लगभग हमेशा अभिलेखागार जैसे .jar या .war फ़ाइलों के रूप में वितरित किया जाता है, और ऐसे मामलों में, एक संसाधन एक अलग फ़ाइल नहीं होगी और न ही लिखने योग्य होगी। (URL वर्ग की getFile विधि इसके लिए कोई समाधान नहीं है; अपने नाम के बावजूद, यह केवल URL के पथ भाग को लौटाता है, जो किसी भी तरह से मान्य फ़ाइल नाम होने की गारंटी नहीं है।)

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

किसी संसाधन से एक छवि लोड हो रही है

बंडल छवि लोड करने के लिए:

package com.example;

public class ExampleApplication {
    private Image getIcon() throws IOException {
        URL imageURL = ExampleApplication.class.getResource("icon.png");
        return ImageIO.read(imageURL);
    }
}

डिफ़ॉल्ट कॉन्फ़िगरेशन लोड हो रहा है

डिफ़ॉल्ट कॉन्फ़िगरेशन गुण पढ़ने के लिए:

package com.example;

public class ExampleApplication {
    private Properties getDefaults() throws IOException {
        Properties defaults = new Properties();

        try (InputStream defaultsStream =
            ExampleApplication.class.getResourceAsStream("config.properties")) {

            defaults.load(defaultsStream);
        }

        return defaults;
    }
}

एकाधिक JAR से समान-नाम संसाधन लोड हो रहा है

क्लासपाथ पर एक से अधिक JAR फ़ाइल में समान पथ और नाम वाले संसाधन मौजूद हो सकते हैं। सामान्य मामले एक सम्मेलन के बाद के संसाधन हैं या जो एक पैकेजिंग विनिर्देशन का हिस्सा हैं। ऐसे संसाधनों के उदाहरण हैं

  • META-INF / MANIFEST.MF
  • मेटा-इन / बीन्स। xml (CDI कल्पना)
  • सेवा प्रदाता संपत्तियों में कार्यान्वयन प्रदाता हैं

अलग-अलग जार में इन सभी संसाधनों तक पहुंचने के लिए, क्लासलैडर का उपयोग करना होगा, जिसके पास इसके लिए एक तरीका है। लौटे Enumeration को कलेक्शन फ़ंक्शन का उपयोग करके आसानी से एक List परिवर्तित किया जा सकता है।

Enumeration<URL> resEnum = MyClass.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
ArrayList<URL> resources = Collections.list(resEnum);

क्लास लोडर का उपयोग करके संसाधनों को खोजना और पढ़ना

जावा में संसाधन लोडिंग में निम्नलिखित चरण शामिल हैं:

  1. Class या ClassLoader ढूंढना जो संसाधन को ClassLoader
  2. संसाधन ढूँढना।
  3. संसाधन के लिए बाइट स्ट्रीम प्राप्त करना।
  4. बाइट स्ट्रीम को पढ़ना और प्रोसेस करना।
  5. बाइट स्ट्रीम को बंद करना।

संसाधन लोड करने के लिए URL को लाइब्रेरी विधि या कंस्ट्रक्टर में पास करके अंतिम तीन चरणों को आमतौर पर पूरा किया जाता है। आप आमतौर पर इस मामले में एक getResource विधि का उपयोग करेंगे। एप्लिकेशन कोड में संसाधन डेटा को पढ़ना भी संभव है। आप आमतौर पर getResourceAsStream का इस मामले में उपयोग करेंगे।

निरपेक्ष और सापेक्ष संसाधन पथ

क्लासपाथ से लोड किए जा सकने वाले संसाधनों को एक मार्ग द्वारा निरूपित किया जाता है। पथ का सिंटैक्स UNIX / Linux फ़ाइल पथ के समान है। इसमें आगे स्लैश ( / ) वर्णों द्वारा अलग किए गए सरल नाम हैं। एक सापेक्ष पथ एक नाम से शुरू होता है, और एक निरपेक्ष पथ एक विभाजक से शुरू होता है।

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

क्लास या क्लास लोडर प्राप्त करना

एक संसाधन या तो एक Class ऑब्जेक्ट या एक ClassLoader ऑब्जेक्ट का उपयोग करके स्थित हो सकता है। एक Class ऑब्जेक्ट रिश्तेदार रास्तों को हल कर सकता है, इसलिए यदि आप एक (वर्ग) रिश्तेदार संसाधन हैं, तो आप आमतौर पर इनमें से एक का उपयोग करेंगे। Class ऑब्जेक्ट प्राप्त करने के विभिन्न तरीके हैं। उदाहरण के लिए:

  • एक वर्ग शाब्दिक आपको किसी भी वर्ग के लिए Class ऑब्जेक्ट देगा जिसे आप जावा स्रोत कोड में नाम दे सकते हैं; जैसे String.class आपको String प्रकार के लिए Class ऑब्जेक्ट देता है।

  • Object.getClass() आपको Class ऑब्जेक्ट को किसी भी ऑब्जेक्ट को टाइप करने के लिए देगा; जैसे "hello".getClass() एक और तरीका है पाने के लिए है Class की String प्रकार।

  • Class.forName(String) विधि (यदि आवश्यक हो) गतिशील रूप से एक कक्षा को लोड करेगी और अपनी Class वस्तु वापस करेगी; उदा। Class.forName("java.lang.String")

एक ClassLoader वस्तु आम तौर पर फोन करके प्राप्त किया जाता है getClassLoader() एक पर Class वस्तु। स्थिर ClassLoader.getSystemClassLoader() पद्धति का उपयोग करके JVM के डिफ़ॉल्ट ClassLoader.getSystemClassLoader() को पकड़ना भी संभव है।

get तरीके

एक बार जब आपके पास एक Class या ClassLoader उदाहरण होता है, तो आप निम्न विधियों में से किसी एक का उपयोग करके एक संसाधन पा सकते हैं:

तरीके विवरण
ClassLoader.getResource(path)
ClassLoader.getResources(path)
एक URL देता है जो दिए गए पथ के साथ संसाधन के स्थान का प्रतिनिधित्व करता है।
ClassLoader.getResources(path)
Class.getResources(path)
एक Enumeration<URL> देता है Enumeration<URL> दे रहा है जिसका उपयोग foo.bar संसाधन का पता लगाने के लिए किया जा सकता है; निचे देखो।
ClassLoader.getResourceAsStream(path)
Class.getResourceStream(path)
एक InputStream देता है जिसमें से आप foo.bar संसाधन की सामग्री को बाइट्स के अनुक्रम के रूप में पढ़ सकते हैं।

टिप्पणियाँ:

  • ClassLoader और Class के तरीकों के बीच का मुख्य अंतर इस तरह से है कि रिश्तेदार पथ की व्याख्या की जाती है।

    • Class तरीके "फ़ोल्डर" में एक रिश्तेदार पथ को हल करते हैं जो कक्षाओं के पैकेज से मेल खाती है।
    • ClassLoader विधियाँ सापेक्ष पथों का उपचार करती हैं जैसे कि वे निरपेक्ष हों; यानी, उन्हें क्लासपैथ नेमस्पेस के "रूट फ़ोल्डर" में हल करें।
  • यदि अनुरोधित संसाधन (या संसाधन) नहीं मिल सकते हैं, तो getResource और getResourceAsStream methods return शून्य हो जाती हैं , and the getResource methods return an empty Enumeration` लौटाती हैं।

  • लौटाए गए URL URL.toStream() का उपयोग करके URL.toStream() उपयोग योग्य हो जाएंगे। वे file: हो सकते हैं file: URL या अन्य पारंपरिक URL, लेकिन यदि संसाधन JAR फ़ाइल में रहता है, तो वे jar: JAR फ़ाइल और उसके भीतर एक विशिष्ट संसाधन की पहचान करने वाले URL।

  • अपने कोड एक का उपयोग करता है getResourceAsStream विधि (या URL.toStream() ) एक प्राप्त करने के लिए InputStream , यह धारा वस्तु को बंद करने के लिए जिम्मेदार है। स्ट्रीम को बंद करने में विफलता के कारण संसाधन रिसाव हो सकता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow