getResourceAsStream अशक्त देता है


182

मैं अपने जावा प्रोजेक्ट के संकलित जार में एक पैकेज के भीतर से एक पाठ फ़ाइल लोड कर रहा हूं। प्रासंगिक निर्देशिका संरचना इस प्रकार है:

/src/initialization/Lifepaths.txt

मेरा कोड एक Class::getResourceAsStreamको वापस करने के लिए कॉल करके एक फ़ाइल लोड करता है InputStream

public class Lifepaths {
    public static void execute() {
        System.out.println(Lifepaths.class.getClass().
            getResourceAsStream("/initialization/Lifepaths.txt"));
    }

    private Lifepaths() {}

    //This is temporary; will eventually be called from outside
    public static void main(String[] args) {execute();}
}

प्रिंट आउट हमेशा प्रिंट होगा null, चाहे मैं कुछ भी उपयोग करूं। मुझे यकीन नहीं है कि ऊपर काम नहीं करेगा, इसलिए मैंने भी कोशिश की है:

  • "/src/initialization/Lifepaths.txt"
  • "initialization/Lifepaths.txt"
  • "Lifepaths.txt"

न ही ये काम। मैंने इस विषय पर अब तक कई प्रश्न पढ़े हैं, लेकिन उनमें से कोई भी मददगार नहीं रहा है - आमतौर पर, वे बस रूट पथ का उपयोग करके फ़ाइलों को लोड करने के लिए कहते हैं, जो मैं पहले से कर रहा हूं। वह, या बस फ़ाइल को वर्तमान निर्देशिका (सिर्फ लोड ) से लोड करें , जो मैंने भी कोशिश की है। फ़ाइल को उपयुक्त नाम के साथ उपयुक्त स्थान पर JAR में संकलित किया जा रहा है। filename

मैं इसे कैसे हल करूं?


3
आप जाँच की कि यह वास्तव में है है जार फ़ाइल में? क्या आपने फ़ाइल आवरण की जाँच की है?
जॉन स्कीट

@JonSkeet यह वास्तव में JAR फ़ाइल में उचित स्थान पर संकलित किया जा रहा है, और मामला सही है।

1
@greedybuddha जबकि मैं उस स्थैतिक संदर्भ से आह्वान नहीं कर सकता, मैं इसका उपयोग करके आह्वान कर सकता हूं Lifepaths.class। कहा जा रहा है, getClassLoader()यह काम करने की अनुमति क्यों देता है? (इसके अलावा, एक उत्तर पोस्ट करने के लिए स्वतंत्र महसूस हो रहा है!)

क्या आप दिखा सकते हैं Lifepaths.getClass()? ऐसा कोई स्थिर विधि वस्तु में परिभाषित किया गया है ...
puce

1
इस उत्तर पर एक नज़र डालें और देखें कि क्या आप इसका उपयोग करके काम कर सकते हैं getResource(String)। बीटीडब्ल्यू - मुझे हमेशा staticसंदर्भ में काम करने के लिए उन समस्याओं में से एक था । मूल रूप से समस्या यह है कि प्राप्त क्लास लोडर जे 2 एसई वर्गों के लिए एक है। आपको संदर्भ वर्ग लोडर तक पहुंच प्राप्त करने की आवश्यकता है जो कि आवेदन के लिए अभिप्रेत है।
एंड्रयू थॉम्पसन

जवाबों:


158

Lifepaths.class.getClass().getResourceAsStream(...) सिस्टम क्लास लोडर का उपयोग करके संसाधनों को लोड करता है, यह स्पष्ट रूप से विफल रहता है क्योंकि यह आपके JAR को नहीं देखता है

Lifepaths.class.getResourceAsStream(...) भारोत्तोलक वर्ग को लोड करने वाले समान श्रेणी लोडर का उपयोग करके संसाधनों को लोड करता है और इसे आपके JAR में संसाधनों तक पहुंच होनी चाहिए


128
बस जोड़ने के लिए, जब getResourceAsStream (नाम) प्राप्त होता है, तो नाम "/" से शुरू होना चाहिए। मुझे यकीन नहीं है कि यह आवश्यक है, लेकिन मुझे इसके बिना समस्या है।
डेविड

3
मैं इस / सुबह से आज सुबह 8 बजे से पंगा ले रहा हूं। मुझे बचाया। मुझे इसे काम करने के लिए एक प्रमुख स्लैश की भी आवश्यकता थी।
काइल २

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

3
@ डेविड - मुझे लगता है कि यह (अग्रणी '/') आवश्यक है अन्यथा यह लाइफ़फेथक्लास पैकेज के सापेक्ष खोजता है
Mz A

5
बस कुछ जानकारी जोड़ने के लिए, आपको /अपनी राह से पहले जोड़ना होगा यदि आपकी फ़ाइल एक अलग निर्देशिका के अधीन है; उदाहरण के लिए initialization/Lifepaths.txt। यदि फ़ाइल का रास्ता है ही yout वर्ग के (लेकिन मुख्य dir के रूप में संसाधनों के तहत) तुम सिर्फ फ़ाइल का नाम किसी भी बिना रख सकते हैं /। उदाहरण के लिए यदि आपकी कक्षा में निम्न पथ है src/main/java/paths/Lifepaths.java, तो आपकी फ़ाइल में यह पथ होना चाहिए src/main/resources/paths/Lifepaths.txt
डॉवित

59

नियम इस प्रकार हैं:

  1. उस फ़ाइल के स्थान की जाँच करें जिसे आप JAR के अंदर लोड करना चाहते हैं (और इस तरह यह भी सुनिश्चित करें कि यह वास्तव में JAR में जोड़ा गया है)
  2. या तो एक निरपेक्ष पथ का उपयोग करें: पथ जार की जड़ पर शुरू होता है
  3. एक सापेक्ष पथ का उपयोग करें: पथ उस श्रेणी के पैकेज निर्देशिका पर शुरू होता है जिसे आप getResource / getResoucreAsStream कहते हैं

और कोशिश:

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

के बजाय

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(यह निश्चित नहीं है कि इससे कोई फर्क पड़ता है, लेकिन पूर्व सही ClassLoader / JAR का उपयोग करेगा, जबकि मुझे बाद में यकीन नहीं है)


2
मैंने इन तीनों चीजों को पहले ही कर लिया है। कृपया मेरे सवाल को फिर से पढ़ें।

आपके प्रश्न से यह स्पष्ट नहीं है कि "प्रासंगिक निर्देशिका संरचना" क्या है और यदि आपने वास्तव में जाँच की है कि क्या फ़ाइल कहाँ और कहाँ JAR में स्थित है (चरण 1)
Puce

1
रिश्तेदार पथ के बारे में आपकी टिप्पणी ने आखिरकार मेरे अंत में इस मुद्दे को हल कर दिया; धन्यवाद!
पॉल बोरमन्स

दिलचस्प। यह पता चला है कि मुझे इसे पाने के लिए "/config.properties" (स्लैश के साथ) करना था ...
Erk

45

तो एक जार से एक संसाधन प्राप्त करने के कई तरीके हैं और प्रत्येक में थोड़ा अलग सिंटैक्स है जहां पथ को अलग तरीके से निर्दिष्ट करने की आवश्यकता होती है।

सबसे अच्छा स्पष्टीकरण मैंने देखा है यह लेख JavaWorld का है । मैं यहाँ संक्षेप में बताऊंगा, लेकिन यदि आप अधिक जानना चाहते हैं तो आपको लेख को देखना चाहिए।

तरीके

1) ClassLoader.getResourceAsStream()

प्रारूप: "/" - अलग किए गए नाम; कोई अग्रणी नहीं "/" (सभी नाम निरपेक्ष हैं)।

उदाहरण: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

2) Class.getResourceAsStream()

प्रारूप: "/" - अलग किए गए नाम; अग्रणी "/" निरपेक्ष नामों को इंगित करता है; अन्य सभी नाम कक्षा के पैकेज के सापेक्ष हैं

उदाहरण: this.getClass().getResourceAsStream("/some/pkg/resource.properties");


आपका दूसरा उदाहरण टूट गया है
जानूस ट्रॉल्सन

1
दूसरा उदाहरण टूटा नहीं है, जैसा कि मैंने कहा उत्तर में यह निर्भर करता है कि संसाधन कहाँ स्थित है।
लालचीबुद्ध

इसके अलावा: सुनिश्चित करें कि आपका आईडीई स्रोत फ़ोल्डर को ताज़ा करके फ़ाइल ('कुछ / pkg / resource.properties') को देखता है।
एरिक डुमिनील

15

निरपेक्ष रास्तों का उपयोग न करें, उन्हें अपनी परियोजना में 'संसाधन' निर्देशिका के सापेक्ष बनाएं। त्वरित और गंदे कोड जो निर्देशिका 'संसाधनों' से MyTest.txt की सामग्री प्रदर्शित करता है।

@Test
public void testDefaultResource() {
    // can we see default resources
    BufferedInputStream result = (BufferedInputStream) 
         Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
    byte [] b = new byte[256];
    int val = 0;
    String txt = null;
    do {
        try {
            val = result.read(b);
            if (val > 0) {
                txt += new String(b, 0, val);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } 
    } while (val > -1);
    System.out.println(txt);
}

9

आप स्ट्रीम प्राप्त करने के लिए इसे पहले आज़माना चाहते हैं और फिर इसे स्ट्रीम के रूप में खोलना चाहते हैं।

URL url = getClass().getResource("/initialization/Lifepaths.txt"); 
InputStream strm = url.openStream(); 

मेरा एक बार भी इसी तरह का सवाल था: जार से txt फाइल पढ़ना विफल रहता है, लेकिन छवि काम करता है


3
यह वास्तव में getResourceAsStream () करता है
Fede

8

लगता है कि आप उपयोग कर रहे ClassLader के साथ समस्या है। क्लास को लोड करने के लिए ReferenceClassLoader का उपयोग करें। यह एक स्थिर / गैर-स्थैतिक विधि में है या नहीं

Thread.currentThread().getContextClassLoader().getResourceAsStream......


5

मैंने खुद को एक ऐसे ही मुद्दे में पाया। चूंकि मैं मावेन का उपयोग कर रहा हूं, मुझे अपने pom.xml को अपडेट करने की आवश्यकता है ताकि कुछ इस तरह से शामिल हो:

   ...
</dependencies>
<build>
    <resources>
        <resource>
            <directory>/src/main/resources</directory>
        </resource>
        <resource>
            <directory>../src/main/resources</directory>
        </resource>
    </resources>
    <pluginManagement>
        ...

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


3

मेरे लिए जो काम किया गया वह फ़ाइल को जोड़ने My Project/Java Resources/srcऔर फिर उपयोग करने के लिए था

this.getClass().getClassLoader().getResourceAsStream("myfile.txt");

मुझे इस फ़ाइल को स्पष्ट रूप से पथ में जोड़ने की आवश्यकता नहीं थी (इसे /srcजाहिरा तौर पर जोड़ना )


गलत जावा सिंटैक्स
इलिया खारलामोव

2

मदद का पता नहीं है, लेकिन मेरे मामले में मेरे पास / src / फ़ोल्डर में मेरा संसाधन था और यह त्रुटि प्राप्त कर रहा था। मैंने फिर बिन फ़ोल्डर में चित्र को स्थानांतरित किया और इसने समस्या को ठीक किया।


2

सुनिश्चित करें कि आपकी संसाधन निर्देशिका (उदाहरण के लिए "src") आपके वर्गपथ में है (सुनिश्चित करें कि यह ग्रहण में आपके निर्माण पथ में एक स्रोत निर्देशिका है)।

सुनिश्चित करें कि मुख्य क्लास लोडर से क्लैज को लोड किया गया है।

फिर, src / initialization / Lifepaths.txt को लोड करने के लिए उपयोग करें

clazz.getResourceAsStream("/initialization/Lifepaths.txt");

क्यों: क्लाज के क्लाथपाठ के भीतरclazz.getResourcesAsStream(foo) से फू दिखाई देता है , डायरेक्टरी क्लैज के सापेक्ष रहता है । प्रमुख "/" इसे किसी भी डायरेक्टरी के मूल से लोड करता है क्लाज़ के क्लासपाथ में।

जब तक आप किसी प्रकार के कंटेनर में नहीं होते हैं, जैसे कि टॉमकैट, या सीधे क्लासऑलर के साथ कुछ कर रहे हैं, तो आप केवल अपने ग्रहण / कमांड लाइन क्लासपाथ को केवल क्लास लोडर क्लासपैथ के रूप में मान सकते हैं।


2

डिफ़ॉल्ट JVM क्लास लोडर पहले संसाधनों को लोड करने के लिए पैरेंट-क्लास लोडर का उपयोग करेगा deletegate-अभिभावक classloader:।

Lifepaths.class.getClass()'क्लास लोडर' है bootstrap classloader, इसलिए getResourceAsStreamकेवल $ JAVA_HOME खोजेगी, चाहे उपयोगकर्ता कोई भी हो classpath। जाहिर है, Lifepaths.txt वहाँ नहीं है।

Lifepaths.classका क्लास लोडर है system classpath classloader, इसलिए getResourceAsStreamउपयोगकर्ता परिभाषित करेगा classpathऔर Lifepaths.txt है।

उपयोग करते समय java.lang.Class#getResourceAsStream(String name), नाम जो '/' से शुरू नहीं होता है, package nameउपसर्ग के साथ जोड़ा जाएगा । यदि आप इससे बचना चाहते हैं, तो कृपया उपयोग करें java.lang.ClassLoader#getResourceAsStream। उदाहरण के लिए:

ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName); 

2

मोटे तौर पर बोल:

getClass().getResource("/") ~ = Thread.currentThread().getContextClassLoader().getResource(".")

मान लीजिए कि आपकी परियोजना संरचना निम्नलिखित की तरह है:

├── src
   ├── main
   └── test
   └── test
       ├── java
          └── com
              └── github
                  └── xyz
                      └── proj
                          ├── MainTest.java
                          └── TestBase.java
       └── resources
           └── abcd.txt
└── target
    └── test-classes
        ├── com
        └── abcd.txt
// in MainClass.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") ->  null

2

यदि आप मावेन का उपयोग कर रहे हैं, तो सुनिश्चित करें कि आपकी पैकिंग 'जार' है, न कि 'पोम'।

<packaging>jar</packaging>

0

क्या आप वास्तव में जरूरत फ़ाइल के लिए एक पूर्ण निरपेक्ष classPath है। इसलिए यह अनुमान लगाने के बजाय, रूट का पता लगाने की कोशिश करें और फिर फ़ाइल को एक बेहतर स्थान आधार <<.war> फ़ाइल स्थान पर ले जाएं ...

URL test1 = getClass().getResource("/");
URL test2 = getClass().getClassLoader().getResource("/");            
URL test3 = getClass().getClassLoader().getResource("../");

logger.info(test1.getPath()); 
logger.info(test2.getPath());
logger.info(test3.getPath());

-1

मेरे लिए क्या काम किया मैं फ़ाइल के तहत रखा गया है

src/main/java/myfile.log

तथा

InputStream is = getClass().getClassLoader().getResourceAsStream("myfile.log");
        
        if (is == null) {
            throw new FileNotFoundException("Log file not provided");
        }

स्रोत फ़ोल्डर को कहा जाता है src/main/JAVA, जाहिर है कि आपकी गैर-कोड फाइलें यहां स्थित नहीं होनी चाहिए।
लीरेन

-12

@Emracool ... मैं आपको एक विकल्प सुझाऊंगा। चूंकि आप एक * .txt फ़ाइल लोड करने का प्रयास कर रहे हैं। FileInputStream()बल्कि इस कष्टप्रद getClass().getClassLoader().getResourceAsStream()या का उपयोग करने के लिए बेहतर है getClass().getResourceAsStream()। कम से कम आपका कोड ठीक से निष्पादित होगा।


क्या ??? -1 ऐसे काम के जवाब के लिए। कोई बात नहीं क्या। लेकिन ऊपर दिए गए समाधान निश्चित रूप से काम करेंगे।
जैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.