getResourceAsStream () बनाम FileInputStream


173

मैं एक वेबप में फ़ाइल लोड करने का प्रयास कर रहा था, और FileNotFoundजब मैं उपयोग करता था तो मुझे एक अपवाद मिल रहा था FileInputStream। हालाँकि, उसी पथ का उपयोग करते हुए, मैं फ़ाइल लोड करने में सक्षम था जब मैंने किया था getResourceAsStream()। दोनों विधियों में क्या अंतर है, और एक काम क्यों नहीं करता है जबकि दूसरा नहीं करता है?

जवाबों:


256

java.io.Fileऔर पत्नी के स्थानीय डिस्क फाइल सिस्टम पर काम करता है। आपकी समस्या का मूल कारण यह है कि सापेक्ष पथ java.ioवर्तमान कार्य निर्देशिका पर निर्भर हैं। यानी वह निर्देशिका जिसमें से JVM (आपके मामले में: वेबसर्वर एक) शुरू किया गया है। इस उदाहरण के लिए हो सकता है C:\Tomcat\binया कुछ और पूरी तरह से अलग है, लेकिन इस प्रकार नहीं C:\Tomcat\webapps\contextname या जो भी आप इसे होने की उम्मीद थी। एक सामान्य ग्रहण परियोजना में, यह होगा C:\Eclipse\workspace\projectname। आप निम्न तरीके से वर्तमान कार्य निर्देशिका के बारे में जान सकते हैं:

System.out.println(new File(".").getAbsolutePath());

हालाँकि, वर्किंग डायरेक्टरी किसी भी तरह से प्रोग्रामेबल कंट्रोल करने योग्य नहीं है। आपको वास्तव में एपीआई के सापेक्ष पथ के बजाय पूर्ण पथ का उपयोग करना चाहिए File। जैसे C:\full\path\to\file.ext

आप जावा (वेब) अनुप्रयोगों में पूर्ण पथ को हार्डकोड या अनुमान नहीं करना चाहते हैं। यह केवल पोर्टेबिलिटी परेशानी है (यानी यह सिस्टम X में चलता है, लेकिन सिस्टम Y में नहीं)। सामान्य अभ्यास क्लासपाथ में उन प्रकार के संसाधनों को रखना है , या क्लासपाथ के लिए अपना पूरा रास्ता जोड़ना है (जैसे आईडीई में वह srcफ़ोल्डर और "बिल्ड पथ" क्रमशः)। इस तरह से आप की मदद से उन्हें प्राप्त कर सकते हैं ClassLoaderद्वारा ClassLoader#getResource()या ClassLoader#getResourceAsStream()। यह क्लासपैथ के "रूट" के सापेक्ष फाइलों का पता लगाने में सक्षम है, जैसा कि आप संयोग से समझ गए हैं। वेबएप्लिकेशंस (या किसी भी अन्य एप्लिकेशन में जो कई क्लास लोडर का उपयोग करता है) के लिए इसके ClassLoaderद्वारा लौटाए गए का उपयोग करने की सिफारिश की जाती है Thread.currentThread().getContextClassLoader()ताकि आप वेबएप संदर्भ को "बाहर" भी देख सकें।

Webapps में एक और विकल्प है ServletContext#getResource()और इसका समकक्ष ServletContext#getResourceAsStream()। यह webफ़ोल्डर सहित वेबप प्रोजेक्ट के सार्वजनिक फ़ोल्डर में स्थित फ़ाइलों तक पहुँचने में सक्षम है /WEB-INFServletContextविरासत में मिली द्वारा सर्वलेट्स में उपलब्ध है getServletContext()विधि, आप कॉल कर सकते हैं यह रूप में है।

यह सभी देखें:


5
@ हवा: संबंधित: stackoverflow.com/questions/7952090/…
BalusC

27

getResourceAsStream वेब ऐप्स के लिए इसे करने का सही तरीका है (जैसा कि आपने पहले ही सीखा है)।

कारण यह है कि यदि आप अपने वेब ऐप को WAR में पैकेज करते हैं तो फ़ाइल सिस्टम से पढ़ना काम नहीं कर सकता है। किसी वेब ऐप को पैकेज करने का यह उचित तरीका है। यह उस तरह से पोर्टेबल है, क्योंकि आप निरपेक्ष फ़ाइल पथ या उस स्थान पर निर्भर नहीं हैं जहाँ आपका ऐप सर्वर स्थापित है।


3
+1 - हालांकि "काम नहीं कर सकता" बहुत मजबूत है। (फाइलसिस्टम से पढ़ना काम करने के लिए बनाया जा सकता है, लेकिन इसे आंशिक रूप से करना एक मुश्किल काम है ... और बहुत अधिक कोड, खासकर अगर संसाधन एक जार में है।)
स्टीफन सी

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

@ स्टेफेन - मुझे नहीं लगता कि "काम नहीं कर सकता" बहुत मजबूत है। यहां तक ​​कि कुछ के रूप में सरल रूप में दो अलग-अलग सर्वरों पर तैनात किए जाने वाले ऐप सर्वर के लिए अलग-अलग पथ इसे तोड़ देंगे। मुद्दा यह है कि आपको अपने डब्ल्यूएआर को यथासंभव आत्म-निहित बनाने की आवश्यकता है। आपकी बात सही है, लेकिन मैं अपने शब्दों पर टिकने जा रहा हूं।
duffymo

14

FileInputStream एक फ़ाइल पथ को लोड करता है जिसे आप जावा प्रोसेस की कार्यशील निर्देशिका से संबंधित के रूप में कंस्ट्रक्टर के पास भेजते हैं । आमतौर पर एक वेब कंटेनर में, यह binफ़ोल्डर जैसा कुछ होता है ।

getResourceAsStream()आपके एप्लिकेशन के क्लासपाथ से एक फ़ाइल पथ लोड करेगा ।


12

FileInputStreamवर्ग अंतर्निहित फाइल सिस्टम के साथ सीधे काम करता है। यदि विचाराधीन फ़ाइल भौतिक रूप से वहां मौजूद नहीं है, तो वह इसे खोलने में विफल रहेगा। getResourceAsStream()विधि अलग तरह से काम करता है। यह ClassLoaderउस कक्षा का उपयोग करके संसाधन को खोजने और लोड करने का प्रयास करता है जिसे यह कहा जाता है। यह इसे खोजने में सक्षम बनाता है, उदाहरण के लिए, jarफ़ाइलों में एम्बेडेड संसाधन ।


खैर, एक जार के भीतर की फाइलें अभी भी एक फाइल सिस्टम में "वर्तमान" हैं, बस अन्य फाइलों में निहित हैं
मैट बी

1
खैर, हां, बिल्कुल। लेकिन वे आमतौर पर फ़ाइल सिस्टम में स्वतंत्र संस्थाओं के रूप में नहीं देखे जाते हैं, जब तक कि आप आवेदन jarप्रारूप फ़ाइल प्रारूप और इसके निहितार्थों के बारे में नहीं जानते हैं । और जावा में, उपयुक्त के ClassLoaderपास यह ज्ञान हो सकता है, जबकि एक सादा FileInputStreamनिश्चित रूप से नहीं।
डिर्क

7

classname.getResourceAsStream () classname के क्लास लोडर के जरिए फाइल लोड करता है। यदि क्लास जार फ़ाइल से आया है, तो वह वह जगह है जहाँ से संसाधन लोड किया जाएगा।

FileInputStream को फाइल सिस्टम से फाइल पढ़ने के लिए उपयोग किया जाता है।


0

मैं यहाँ दोनों पढ़ों को फाइल रीड (java.io) और रिसोर्स रीड (ClassLoader.getResourceAsStream ()) के रूप में चिह्नित करके अलग कर रहा हूँ।

फ़ाइल पढ़ें - 1. स्थानीय फ़ाइल सिस्टम पर काम करता है। 2. वर्तमान जेवीएम लॉन्च की गई निर्देशिका से अनुरोधित फ़ाइल को रूट के रूप में खोजने की कोशिश करता है। 3. पूर्व-निर्धारित स्थान, / dev / फ़ाइलों या C: \ Data में प्रसंस्करण के लिए फ़ाइलों का उपयोग करते समय आदर्श रूप से अच्छा है।

संसाधन पढ़ें - 1. कक्षा पथ पर काम करता है 2. वर्तमान या मूल अभिभावक वर्गपथ में फ़ाइल / संसाधन का पता लगाने की कोशिश करता है। 3. युद्ध या जार जैसी पैकेज्ड फाइलों से फाइलों को लोड करने की कोशिश करते समय आदर्श रूप से अच्छा है।

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