2010-05-08 13 views
19

के माध्यम से चलते समय फ़ाइल नहीं मिल सकता है जब मैं जावा एप्लिकेशन चलाता हूं जो ग्रहण में फ़ाइल से पढ़ना चाहिए, तो मुझे java.io.FileNotFoundException मिलता है, भले ही फ़ाइल सही निर्देशिका में हो। मैं कमांड लाइन से आवेदन को संकलित और चला सकता हूं ठीक है; समस्या केवल एक से अधिक परियोजना और अनुप्रयोग के साथ ग्रहण में होती है। क्या कोई सेटिंग है जिसे मुझे रन कॉन्फ़िगरेशन में बदलने या फ़ाइल को सही तरीके से ढूंढने के लिए पथ बनाने की आवश्यकता है?जावा ग्रहण

+1

अपना कोड देखे बिना, हम आपको नहीं बता सकते कि –

उत्तर

28

समस्या सबसे अधिक संभावना है कि आपके आवेदन एक रिश्तेदार पथ नाम का उपयोग कर रहा है। जैसा कि @ बालुससी कहते हैं, सापेक्ष पथनाम समस्याग्रस्त हो सकते हैं। लेकिन आईएमओ, जब वह कहता है तो वह बहुत दूर जाता है "[y] कहां कभी java.io सामान में सापेक्ष पथ का उपयोग नहीं करता"

किसी एप्लिकेशन (उदाहरण के लिए) का उपयोग कर FileInputStream(File) निर्माता एक फ़ाइल को खोलता है, रिश्तेदार pathnames "वर्तमान निर्देशिका" एक प्रक्रिया के रूप में File.getAbsolutePath() के लिए जावाडोक में इस प्रकार वर्णित के सापेक्ष हल कर रहे हैं।

[...] अन्यथा यह पथनाम सिस्टम-निर्भर तरीके से हल किया गया है। यूनिक्स सिस्टम पर, वर्तमान उपयोगकर्ता निर्देशिका के विरुद्ध इसे हल करके एक सापेक्ष पथनाम पूर्ण किया जाता है। माइक्रोसॉफ्ट विंडोज सिस्टम पर, एक सापेक्ष पथनाम पथनाम द्वारा नामित ड्राइव की वर्तमान निर्देशिका के विरुद्ध इसे हल करके पूर्ण किया जाता है, यदि कोई हो; यदि नहीं, तो यह वर्तमान उपयोगकर्ता निर्देशिका के खिलाफ हल किया गया है।

तो तुरंत, हम देखते हैं कि "वर्तमान निर्देशिका" की धारणा विंडोज और यूनिक्स प्लेटफॉर्म पर अलग-अलग बारीकियों की है। दूसरा मुद्दा यह है कि शुद्ध जावा में आप निश्चित रूप से यह नहीं जान सकते कि वर्तमान निर्देशिका क्या है, और आप निश्चित रूप से शुद्ध जावा का उपयोग कर वर्तमान JVM के लिए इसे नहीं बदल सकते हैं। (जब JVM प्रारंभ होता है, तो "user.dir" सिस्टम प्रॉपर्टी वर्तमान निर्देशिका पर सेट होती है, लेकिन संपत्ति को बदलने से कोई एप्लिकेशन रोक नहीं रहा है, इसलिए आप पूरी तरह से इस पर भरोसा नहीं कर सकते हैं। इसके अलावा, "user.dir" को बदलना केवल खाली पथ को हल करने के तरीके को बदलता है, सामान्य रूप से सापेक्ष पथ नहीं।)

तो आप इसके बारे में क्या करना चाहिए?

  • एक विकल्प फ़ाइलों का संदर्भ देने के लिए पूर्ण पथनामों का उपयोग करना है। यह सभी मामलों में लगभग (लगभग) विश्वसनीय है, लेकिन यदि उपयोगकर्ता को हार्ड-वायर्ड (या कॉन्फ़िगर किए गए) पूर्ण पथनाम से बचने की आवश्यकता है, तो उपयोगकर्ता को पथनाम, या दर्ज करना होगा, तो पूर्ण पथनाम का उपयोग समस्याग्रस्त हो सकता है।

  • क्लासपाथ सापेक्ष पथनामों का उपयोग करने और एप्लिकेशन की स्थापना निर्देशिका से संबंधित फ़ाइलों का पता लगाने का दूसरा विकल्प है। यह काम करता है यदि आपको ऐसा करने की ज़रूरत है, लेकिन यदि आपको कुछ लाइब्रेरी विधि में File पास करने की आवश्यकता है तो समस्या उत्पन्न होती है। यदि आप उपयोगकर्ता की एप्लिकेशन प्राथमिकताओं को खोजने का प्रयास कर रहे हैं तो यह भी मदद नहीं करता है। (सामान्य रूप से, स्थापना निर्देशिका में उपयोगकर्ता वरीयताओं को रखना एक गलती है ...)

  • एक तीसरा विकल्प किसी अन्य निर्देशिका से संबंधित किसी फ़ाइल को नामित करना है जिसे आप कहीं और से प्राप्त करते हैं; जैसे new File(System.getProperty("home.dir"), "foo/bar");

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

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

+0

आपकी मदद के लिए धन्यवाद! – derekerdmann

+0

ग्रहण से लॉन्च किए गए मेरे ऐप के साथ कोई समस्या थी, जो मेरी प्रोजेक्ट की जड़ में कुछ गुण फ़ाइल को पढ़ने में सक्षम नहीं था।चलाने के बाद मैंने $ {workspace_loc}/myproject/bin पर काम कॉन्फ़िगरेशन में कार्य निर्देशिका सेट करने का प्रयास किया, यह काम किया! – Krishnaraj

+0

@ कृष्णाराज - मैंने अपने उत्तर के अंतिम अनुच्छेद में यही कहा :-) –

6

जब आप ग्रहण में एक डिफ़ॉल्ट जावा अनुप्रयोग बनाने के लिए, आप इस निर्देशिका संरचना मिलती है: - रूट निर्देशिका
./ProjectName/bin/ -

./ProjectName/ उत्पादन निर्देशिका, .class युक्त फ़ाइलों
./ProjectName/src/ - स्रोत निर्देशिका, जावा फ़ाइलों

युक्त यदि आपका आवेदन अनुरोध "./data.txt" यह के लिए खोज करेंगे यह रूट निर्देशिका के सापेक्ष। यह "कामकाजी निर्देशिका" है और ऊपर मार्टिन के उत्तर के अनुसार तर्क टैब में कॉन्फ़िगर किया जा सकता है।

आप कहते हैं कि यह कमांड लाइन से काम करता है? यह संभव है क्योंकि जब आप जावा बाइनरी चलाते हैं तो आप या तो बिन या src फ़ोल्डर्स के अंदर होते हैं। इस मामले में कार्यशील निर्देशिका वह भी है जो कमांड प्रॉम्प्ट वर्तमान में अंदर है। यदि, उदाहरण के लिए, आप/src/निर्देशिका में जाते हैं, javac *.java कहें तो वहां से फ़ाइलें चलाएं, यह/src/निर्देशिका में "./data.txt" की खोज करेगा। यदि आप/bin/निर्देशिका के अंदर जाते हैं और वहां से अपना एप्लिकेशन चलाते हैं, तो यह/bin/निर्देशिका से संबंधित फ़ाइल की तलाश करेगा।

+0

आपकी सहायता के लिए धन्यवाद क्या हो सकता है। मुझे आवश्यक टेक्स्ट फाइलें/bin/निर्देशिका में मौजूद हैं, इसलिए यह समस्या प्रतीत नहीं होती है। मैं सापेक्ष पथ के साथ खेलूँगा और देखें कि मैं क्या प्राप्त कर सकता हूं। – derekerdmann

2

आपको कभीjava.io सामान में सापेक्ष पथ का उपयोग करना चाहिए। पथ वर्तमान कार्यशील निर्देशिका पर निर्भर हो जाएगा, जो इस बात पर निर्भर करता है कि आपने एप्लिकेशन को कैसे शुरू किया और इस प्रकार सभी वातावरणों पर समान नहीं है। यह जावा एप्लिकेशन के अंदर से अनियंत्रित है। पोर्टेबिलिटी मुसीबत! हमेशा पूर्ण पथ का उपयोग करें। इस प्रकार उदा। यूनिक्स और कंसोर्ट्स के लिए c:/path/to/file.ext या /path/to/file.ext (अग्रणी स्लैश के साथ) (या यहां तक ​​कि विंडोज़ जब डिस्क अक्षर अप्रासंगिक है)।

जब भी आप अपने आवेदन के साथ कुछ फाइलों को शिप करना चाहते हैं, तो एक सामान्य अभ्यास उन्हें क्लासपाथ में भी रखना है। इस तरह आप अपना स्थान प्राप्त करने के लिए बस ClassLoader#getResource() का उपयोग कर सकते हैं। यह URL देता है। आप URL#toURI() या URL#getPath() का उपयोग कर सकते हैं और java.io.File के निर्माता को पास कर सकते हैं और फिर इसे सामान्य तरीके से आगे बढ़ा सकते हैं।

अपनी ग्रहण परियोजना में, src फ़ोल्डर (जहां आपका जावा स्रोत जाता है) मूल रूप से क्लासपाथ की जड़ है। इसके अलावा यह निश्चित रूप से अन्य सभी परियोजनाओं और (बाहरी) फ़ोल्डरों को भी शामिल करता है जो परियोजना के बिल्ड पथ में ले जाया जाता है।

मान लिया जाये कि आप जड़ classpath की में विशेष फ़ाइल रखी है कि:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
URL url = classLoader.getResource("file.ext"); 
File file = new File(url.getPath()); 
FileInputStream input = new FileInputStream(file); 
// ... 

तुम भी ClassLoader#getResourceAsStream() का उपयोग सीधे एक InputStream प्राप्त करने के लिए कर सकते हैं:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
InputStream input = classLoader.getResourceAsStream("file.ext"); 
// ... 

यदि यह रखा है एक पैकेज के अंदर, आप केवल सामान्य पथनाम का उपयोग कर सकते हैं:

URL url = classLoader.getResource("com/example/file.ext"); 
// ... 

या

InputStream input = classLoader.getResourceAsStream("com/example/file.ext"); 
// ... 
+0

एक गैर-जीयूआई कमांड लाइन एप्लिकेशन उचित रूप से सापेक्ष पथनामों का उपयोग करने के लिए डिज़ाइन किया जा सकता है। चेतावनी यह है कि उपयोगकर्ता को "वर्तमान निर्देशिका" की अवधारणा को समझने की आवश्यकता है, और प्रोग्रामर को यह समझने की आवश्यकता है कि जावा आईओ पुस्तकालयों के व्यवहार के लिए यह मानचित्र कैसा है। –

+0

@ स्टीफन: यह निश्चित रूप से संभव है, आपको केवल सापेक्ष पथों से परेशानी होगी, लेकिन इसकी अनुशंसा नहीं की जाती है। क्लासपाथ का लाभ लेना इसे और अधिक मजबूत बनाता है। – BalusC

+0

यह इस बात पर निर्भर करता है कि एप्लिकेशन क्या कर रहा है। उदाहरण के लिए, यदि यह उपयोगकर्ता द्वारा आपूर्ति की गई फ़ाइलों में हेरफेर कर रहा है, तो क्लासपाथ दृष्टिकोण थोड़ा समझ में आता है। –

1

मानते हैं कि उपयोगकर्ता फ़ाइल फ़ाइल में पूर्ण फ़ाइल पथ दर्ज नहीं करता है और "myfilenameonly" जैसा कुछ दर्ज करता है। File file = new File(".", args[0]) इस मामले में फ़ाइल को ढूंढें (पहले तर्क को ध्यान में रखते हुए) का पता लगाएं।

सभी प्लेटफार्मों: File.getParent() मूल निर्देशिका वापस नहीं करता है, इसे वापस चाहिए ".." या एक फ़ाइल-प्रणाली विशिष्ट तरीके से मूल निर्देशिका का नाम है।

आप फ़ाइल "myfilenameonly" निर्देशिका जहां यह स्थित है के लिए पूरा पथ निर्दिष्ट किए बिना बनाते हैं, तो File.getParent(), उदाहरण के लिए, अशक्त वापस आ जाएगी।

आगे देखें: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=1228537

2

मैं एक ऐसी ही समस्या हो रही थी, मैं अपने फ़ाइलें एक फ़ोल्डर में नाम cobolcopybooks src फ़ोल्डर के अंदर रखा जाता है और अपने प्रोजेक्ट classloader.getResource का उपयोग कर ("cobolcopybooks/demostud अंदर उन तक पहुँचने की कोशिश की। कोब ") लेकिन मुझे शून्य सूचक अपवाद मिल रहा था, मैंने कई विफल प्रयासों के बाद कार्यक्षेत्रों की सफाई और निर्माण करके इसे कई बार कोशिश की, मुझे एहसास हुआ कि मैं प्रोजेक्ट के साथ फाइलों को बनाने की अनुमति देने के लिए प्रोजेक्ट को रीफ्रेश नहीं कर रहा था। यानी इन फ़ाइलों को अन्य कक्षा फ़ाइलों के साथ रनटाइम के रूप में दिखाई देना चाहिए, रूट निर्देशिका बिन निर्देशिका होगी और यह उन फ़ाइलों को खोज रही है।

8

एक और विकल्प यह पता लगाने के लिए है कि आपके वर्तमान वातावरण में "वर्तमान पथ" क्या निर्देशिका है - जो कुछ भी है। एक बार पता लगाने के बाद, आप वहां से अपना समाधान चुन सकते हैं। हो सकता है कि आपकी फ़ाइल के स्थान के लिए उपयुक्त सापेक्ष पथ का उपयोग करें या फ़ाइल को स्थानांतरित करना है।

File testFile = new File(""); 
    String currentPath = testFile.getAbsolutePath(); 
    System.out.println("current path is: " + currentPath); 
+1

यह शिपिंग कोड में आदर्श नहीं है, लेकिन यह निश्चित रूप से डीबग कोड के रूप में उपयोगी है यह देखने के लिए कि आपका एप्लिकेशन क्या सोच रहा है। – Steve

संबंधित मुद्दे