Class.getResource () और ClassLoader.getResource () के बीच अंतर क्या है?


194

मुझे आश्चर्य है कि क्या अंतर है Class.getResource()और ClassLoader.getResource()?

संपादित करें: मैं विशेष रूप से जानना चाहता हूं कि क्या कोई कैशिंग फ़ाइल / निर्देशिका स्तर पर शामिल है। के रूप में "निर्देशिका लिस्टिंग वर्ग संस्करण में कैश्ड हैं?"

AFAIK निम्नलिखित अनिवार्य रूप से एक ही करना चाहिए, लेकिन वे नहीं हैं:

getClass().getResource() 
getClass().getClassLoader().getResource()

मुझे यह पता चला जब कुछ रिपोर्ट जनरेशन कोड के साथ फ़िडलिंग WEB-INF/classes/जो उस निर्देशिका में एक मौजूदा फ़ाइल से एक नई फ़ाइल बनाता है । कक्षा से विधि का उपयोग करते समय, मैं उन फ़ाइलों को खोज सकता था जो तैनाती का उपयोग कर रहे थे getClass().getResource(), लेकिन जब नई बनाई गई फ़ाइल लाने की कोशिश कर रहे थे, तो मैंने एक अशक्त वस्तु प्राप्त की। निर्देशिका को ब्राउज़ करने से स्पष्ट रूप से पता चलता है कि नई फ़ाइल वहां मौजूद है। फ़ाइल नाम "/myFile.txt" के रूप में फ़ॉरवर्ड स्लैश से बनाए गए थे।

ClassLoaderके संस्करण getResource()दूसरी ओर उत्पन्न फ़ाइल मिला। इस अनुभव से ऐसा लगता है कि निर्देशिका लिस्टिंग के कुछ प्रकार की कैशिंग चल रही है। क्या मैं सही हूं, और यदि हां, तो यह दस्तावेज कहां है?

से एपीआई डॉक्स परClass.getResource()

किसी दिए गए नाम के साथ एक संसाधन ढूँढता है। किसी दिए गए वर्ग से जुड़े संसाधनों की खोज करने के नियम कक्षा के डिफाइनिंग क्लास लोडर द्वारा लागू किए जाते हैं। यह विधि इस ऑब्जेक्ट के क्लास लोडर को दर्शाती है। यदि यह ऑब्जेक्ट बूटस्ट्रैप क्लास लोडर द्वारा लोड किया गया था, तो विधि ClassLoader.getSystemResource (java.lang.String) को सौंपती है।

मेरे लिए, यह पढ़ता है "Class.getResource वास्तव में अपने स्वयं के क्लास लोडर को getResource ()" कह रहा है। जो करने जैसा ही होगा getClass().getClassLoader().getResource()। लेकिन यह स्पष्ट रूप से नहीं है। क्या कोई मुझे इस मामले में कुछ रोशनी प्रदान कर सकता है?

जवाबों:


6

इस सवाल का जवाब देने के लिए कि क्या कोई कैशिंग चल रहा है।

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

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

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


मैंने भी मावेन और इंटेलीज का उपयोग किया है, इसलिए यह उत्तर एक ऐसा वातावरण है, जो मेरे सबसे करीब से मेल खाता है और प्रश्न # 2 के लिए एक उचित स्पष्टीकरण है।
ऑलिगॉफ्रेन

250

Class.getResourceएक "रिश्तेदार" संसाधन नाम ले सकता है, जिसे कक्षा के पैकेज के सापेक्ष व्यवहार किया जाता है। वैकल्पिक रूप से आप एक अग्रणी स्लैश का उपयोग करके "निरपेक्ष" संसाधन नाम निर्दिष्ट कर सकते हैं। क्लास लोडर संसाधन पथ हमेशा निरपेक्ष माने जाते हैं।

तो मूल रूप से निम्नलिखित समान हैं:

foo.bar.Baz.class.getResource("xyz.txt");
foo.bar.Baz.class.getClassLoader().getResource("foo/bar/xyz.txt");

और इसलिए ये हैं (लेकिन वे ऊपर से अलग हैं):

foo.bar.Baz.class.getResource("/data/xyz.txt");
foo.bar.Baz.class.getClassLoader().getResource("data/xyz.txt");

स्पष्ट उदाहरणों के साथ अच्छा जवाब। हालाँकि पोस्ट वास्तव में दो सवालों के जवाब पाने के लिए थी, लेकिन अब मैं देख रहा हूं कि दूसरा प्रश्न छिपा हुआ है। यह बताने के लिए कि मुझे इस पोस्ट को कैसे अपडेट करना चाहिए, लेकिन मैं दूसरा जानना चाहता हूं कि यह क्या है (अगली टिप्पणी):
ऑलिगॉफ्रेन

2
क्या Class.getResource () संस्करण में किसी प्रकार की कैशिंग चल रही है? क्या मुझे विश्वास है कि यह कुछ जैस्पर रिपोर्ट की पीढ़ी है: हम जैस्पर xml फ़ाइल लाने के लिए getClass ()। GetResource ("/ aDocument.jrxml") का उपयोग करते हैं। एक बाइनरी जैस्पर फ़ाइल तब उसी निर्देशिका में निर्मित होती है । getClass ()। getResource ("/ aDocument.jasper") इसे ढूंढने में सक्षम नहीं है, हालांकि यह स्पष्ट रूप से एक ही स्तर (इनपुट फ़ाइल) पर दस्तावेज़ पा सकता है। यह वह जगह है जहाँ ClassLoader.getResource () उपयोगी साबित हुआ, क्योंकि ऐसा लगता है कि यह निर्देशिका लिस्टिंग के कैशिंग का उपयोग नहीं करता है। लेकिन मुझे इस पर प्रलेखन नहीं मिला।
ऑलिगॉफ्रेन

2
@oligofren: हम्म ... मैं किसी भी कैशिंग करने के लिए Class.getResource () की उम्मीद नहीं करूंगा ...
जॉन स्कीट

1
@JonSkeet क्यों this.getClass().getClassLoader().getResource("/");लौट रही है अशक्त? यह समान नहीं होना चाहिएthis.getClass().getClassLoader().getResource(".");
आसिफ मुश्ताक

@UnKnown: मुझे लगता है कि आपको शायद उस बारे में एक नया सवाल पूछना चाहिए।
जॉन स्कीट

22

पहला कॉल .classफ़ाइल के सापेक्ष खोजता है जबकि बाद वाला क्लासपाथ रूट के सापेक्ष खोजता है।

इस तरह के मुद्दों को डीबग करने के लिए, मैं URL प्रिंट करता हूं:

System.out.println( getClass().getResource(getClass().getSimpleName() + ".class") );

3
मुझे लगता है कि "क्लास लोडर रूट" "क्लासपैथ रूट" की तुलना में अधिक सटीक होगा - सिर्फ पिकी होने के लिए।
जॉन स्कीट

4
दोनों "पूर्ण पथ" खोज सकते हैं यदि फ़ाइल का नाम "/" से
जुड़ा हुआ है

2
दिलचस्प ... मैं एक केस मार रहा हूँ जहाँ getClass ()। GetResource ("/ someAbsPath") प्रकार /path/to/mylib.jar//someAbsPath और getClass () में एक URL लौटाता है। getClassLoafer () .Resource (" / someAbsPath ") वापसी अशक्त ... तो" क्लासलोडर की जड़ "लगता है कि एक बहुत अच्छी तरह से परिभाषित धारणा नहीं है ...
पियरे हेनरी


8
@PierreHenry: getClassLoader().getResource("/...")हमेशा रिटर्न null- क्लास लोडर अग्रणी /को पथ से नहीं हटाता है , इसलिए लुकअप हमेशा विफल रहता है। केवल क्लासपैथ के सापेक्ष एक निरपेक्ष पथ के रूप में getClass().getResource()एक शुरुआत /को संभालता है ।
एरोन दिगुल्ला

17

इसे चश्मे में देखना था:

क्लास का getResource () - प्रलेखन में अंतर बताया गया है:

यह विधि संसाधन के नाम में ये परिवर्तन करने के बाद, अपने क्लास लोडर को कॉल को दर्शाती है: यदि संसाधन नाम "/" से शुरू होता है, तो यह अपरिवर्तित है; अन्यथा, पैकेज नाम को परिवर्तित करने के बाद संसाधन के नाम से पहले रखा गया है "।" सेवा "/"। यदि यह ऑब्जेक्ट बूटस्ट्रैप लोडर द्वारा लोड किया गया था, तो कॉल ClassLoader.getSystemResource पर भेजा जाता है।


2
क्या आपके पास इस बारे में कोई जानकारी है कि क्या यह निर्देशिका सूची को भी कैश करता है? जब इनपुट फ़ाइल को पहली बार देख रहे थे, और तब उसी निर्देशिका में इसका उपयोग करके एक फ़ाइल बना रहे थे, तो दो तरीकों के बीच यह मुख्य अंतर था। क्लास के संस्करण को यह नहीं मिला, ClassLoader संस्करण ने किया (दोनों "/file.txt" का उपयोग करके)।
ऑलिगॉफ्रेन

11

यहाँ इन सभी उत्तरों के साथ-साथ इस प्रश्न के उत्तर भी सुझाते हैं कि "/foo/bar.properties" जैसे पूर्ण URL को लोड करके class.getResourceAsStream(String)और उसी के समान व्यवहार किया गया है class.getClassLoader().getResourceAsStream(String)। यह ऐसा नहीं है, कम से कम मेरे टॉमकैट कॉन्फ़िगरेशन / संस्करण (वर्तमान में 7.0.40) में नहीं है।

MyClass.class.getResourceAsStream("/foo/bar.properties"); // works!  
MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work!

क्षमा करें, मेरे पास पूरी तरह से कोई संतोषजनक स्पष्टीकरण नहीं है, लेकिन मुझे लगता है कि टॉमकैट गंदे चालें करता है और अपने काले जादू को क्लास लोडर के साथ करता है और अंतर का कारण बनता है। मैं हमेशा class.getResourceAsStream(String)अतीत में इस्तेमाल किया और कोई समस्या नहीं है।

पुनश्च: मैंने भी इसे यहाँ पोस्ट किया है


यह व्यवहार टॉमकैट में एक बग प्रतीत होता है जो संस्करण 8 में तय किया गया था। मैंने इस प्रश्न के बारे
लॉर्डऑफइंप्ल्स

2

Class.getResourcesक्लास लोडर द्वारा संसाधन को पुनः प्राप्त करेगा जो वस्तु को लोड करता है। जबकि ClassLoader.getResourceनिर्दिष्ट वर्कलोडर का उपयोग करके संसाधन को पुनः प्राप्त करेगा।


0

मैंने input1.txt से पढ़ने की कोशिश की, जो मेरे एक पैकेज के अंदर एक साथ उस वर्ग के साथ था जो इसे पढ़ने की कोशिश कर रहा था।

निम्नलिखित कार्य:

String fileName = FileTransferClient.class.getResource("input1.txt").getPath();

System.out.println(fileName);

BufferedReader bufferedTextIn = new BufferedReader(new FileReader(fileName));

getPath()यदि आप स्ट्रिंग प्रारूप में सही पथ का नाम चाहते हैं तो सबसे महत्वपूर्ण हिस्सा कॉल करना था। उपयोग न करेंtoString() क्योंकि यह कुछ अतिरिक्त स्वरूपण पाठ जोड़ देगा जो फ़ाइल को पूरी तरह से बंद कर देगा (आप इसे आज़मा सकते हैं और प्रिंट आउट देख सकते हैं)।

इसे डिबग करने में 2 घंटे का समय लगा ... :(


Class.getResourceAsStream () के बारे में क्या ?
लू ५५

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