2010-07-30 18 views
51

मैं एक XML फ़ाइल को पढ़ना चाहता हूं जो jar में से किसी एक के अंदर स्थित है जो मेरे वर्ग पथ में शामिल है। मैं jar में शामिल किसी भी फ़ाइल को कैसे पढ़ सकता हूं?जावा में जार से फ़ाइल कैसे पढ़ा जाए?

+0

देखें http://stackoverflow.com/questions/16842306 – yegor256

+0

यदि आप फ़ाइलों के लिए किसी भी संख्या के साथ जार में निर्देशिका से फ़ाइलों को पढ़ना चाहते हैं, तो [Stackoverflow-Link] (https://stackoverflow.com/questions/26185137/ देखें वसंत-बूट-संसाधन-नहीं मिला-जब-उपयोग-निष्पादन योग्य-जार/39818817 # 39818817) –

उत्तर

102

आप अपने आवेदन उपयोग अंदर से उस फ़ाइल को पढ़ना चाहते हैं:

InputStream input = getClass().getResourceAsStream("/classpath/to/my/file"); 

पथ "/" के साथ शुरू होता है, लेकिन है कि आपकी फ़ाइल-प्रणाली में पथ नहीं है, लेकिन अपने classpath में। तो यदि आपकी फ़ाइल क्लासपाथ "org.xml" पर है और इसे myxml.xml कहा जाता है तो आपका पथ "/org/xml/myxml.xml" जैसा दिखता है।

इनपुटस्ट्रीम आपकी फ़ाइल की सामग्री को पढ़ता है। यदि आप चाहें तो इसे रीडर में लपेट सकते हैं।

मुझे उम्मीद है कि इससे मदद मिलती है।

+17

+1 यह बताते हुए कि अग्रणी "/" क्यों आवश्यक है। –

46

आह, यह मेरे पसंदीदा विषयों में से एक है। अनिवार्य रूप से आप दो तरह से classpath के माध्यम से संसाधन लोड कर सकते हैं:

Class.getResourceAsStream(resource) 

और

ClassLoader.getResourceAsStream(resource) 

(फिर अन्य तरीकों से इसी तरह से संसाधन के लिए एक URL आ जाए, देखते हैं इसके साथ एक कनेक्शन खोलना, लेकिन ये दो प्रत्यक्ष तरीके हैं)।

पहला तरीका वास्तव में संसाधन नाम को उलझाने के बाद दूसरे स्थान पर जाता है। अनिवार्य रूप से दो प्रकार के संसाधन नाम हैं: पूर्ण (उदा। "/ पथ/से/संसाधन/संसाधन") और रिश्तेदार (उदा। "संसाधन")। पूर्ण पथ "/" से शुरू होते हैं।

यहां एक उदाहरण है जिसे स्पष्ट करना चाहिए। एक वर्ग com.example.A पर विचार करें। क्लासपाथ में दो संसाधनों पर विचार करें, एक/कॉम/उदाहरण/नेस्टेड पर स्थित है, दूसरा/शीर्ष पर।

 
package com.example; 

public class A { 

    public static void main(String args[]) { 

     // Class.getResourceAsStream 
     Object resource = A.class.getResourceAsStream("nested"); 
     System.out.println("1: A.class nested=" + resource); 

     resource = A.class.getResourceAsStream("/com/example/nested"); 
     System.out.println("2: A.class /com/example/nested=" + resource); 

     resource = A.class.getResourceAsStream("top"); 
     System.out.println("3: A.class top=" + resource); 

     resource = A.class.getResourceAsStream("/top"); 
     System.out.println("4: A.class /top=" + resource); 

     // ClassLoader.getResourceAsStream 
     ClassLoader cl = A.class.getClassLoader(); 
     resource = cl.getResourceAsStream("nested");   
     System.out.println("5: cl nested=" + resource); 

     resource = cl.getResourceAsStream("/com/example/nested"); 
     System.out.println("6: cl /com/example/nested=" + resource); 
     resource = cl.getResourceAsStream("com/example/nested"); 
     System.out.println("7: cl com/example/nested=" + resource); 

     resource = cl.getResourceAsStream("top"); 
     System.out.println("8: cl top=" + resource); 

     resource = cl.getResourceAsStream("/top"); 
     System.out.println("9: cl /top=" + resource); 
    } 

} 

कार्यक्रम से उत्पादन होता है:

 
1: A.class [email protected] 
2: A.class /com/example/[email protected] 
3: A.class top=null 
4: A.class /[email protected] 
5: cl nested=null 
6: cl /com/example/nested=null 
7: cl com/example/[email protected] 
8: cl [email protected] 
9: cl /top=null 

अधिकतर बातें करते हैं आप उम्मीद थी क्या निम्नलिखित कार्यक्रम दो संसाधनों का उपयोग करने के लिए नौ संभव तरीके को दर्शाता है। केस -3 विफल रहता है क्योंकि क्लास रिश्तेदार समाधान वर्ग के संबंध में है, इसलिए "शीर्ष" का अर्थ है "/ com/example/top", लेकिन "/ top" का अर्थ यह है कि यह क्या कहता है।

केस -5 विफल रहता है क्योंकि क्लासलोडर रिश्तेदार समाधान क्लासलोडर के संबंध में है। लेकिन, अप्रत्याशित रूप से केस -6 भी विफल रहता है: किसी को ठीक से हल करने के लिए "/ com/example/nested" की उम्मीद हो सकती है। क्लासलोडर के माध्यम से नेस्टेड संसाधन तक पहुंचने के लिए आपको केस -7 का उपयोग करने की आवश्यकता है, यानी नेस्टेड पथ क्लासलोडर की जड़ से संबंधित है। इसी प्रकार केस -9 विफल रहता है, लेकिन केस -8 गुजरता है।

याद रखें: java.lang.Class, getResourceAsStream() के लिए classloader प्रतिनिधि करता है:

 
    public InputStream getResourceAsStream(String name) { 
     name = resolveName(name); 
     ClassLoader cl = getClassLoader0(); 
     if (cl==null) { 
      // A system class. 
      return ClassLoader.getSystemResourceAsStream(name); 
     } 
     return cl.getResourceAsStream(name); 
    } 

तो यह() resolveName के व्यवहार कि महत्वपूर्ण है।

अंत में, चूंकि यह क्लासलोडर का व्यवहार है जो कक्षा को लोड करता है जो अनिवार्य रूप से प्राप्त करता है ResourceAsStream(), और क्लासलोडर अक्सर एक कस्टम लोडर होता है, तो संसाधन लोडिंग नियम और भी जटिल हो सकते हैं। जैसेवेब अनुप्रयोगों के लिए, वेब अनुप्रयोग के संदर्भ में वेब-आईएनएफ/कक्षाओं या वेब-आईएनएफ/lib से लोड, लेकिन अलग-अलग अन्य वेब-अनुप्रयोगों से नहीं। साथ ही, अच्छी तरह से व्यवहार किए गए क्लासलोडर्स माता-पिता को प्रतिनिधि देते हैं, ताकि क्लासपाथ में डुप्लिकेट संसाधन इस तंत्र का उपयोग करके पहुंच योग्य न हों।

+0

यह अनिवार्य रूप से वही उत्तर है जो मैंने दिया है, लेकिन इसमें बहुत समझाया गया है अधिक जानकारी। +1 – Mnementh

+0

यहां संकल्प नाम विधि का उल्लेख किया गया है: https://gist.github.com/briangordon/5374626 –

2

एक जेएआर मूल रूप से एक ज़िप फ़ाइल है इसलिए इसे इस तरह से इलाज करें। नीचे एक फ़ाइल को WAR फ़ाइल से निकालने के तरीके पर एक उदाहरण दिया गया है (इसे एक ज़िप फ़ाइल के रूप में भी देखें) और स्ट्रिंग सामग्री आउटपुट करता है। बाइनरी के लिए आपको निष्कर्षण प्रक्रिया को संशोधित करने की आवश्यकता होगी, लेकिन इसके लिए वहां कई उदाहरण हैं।

<dependency> 
    <groupId>commons-io</groupId> 
    <artifactId>commons-io</artifactId> 
    <version>2.4</version> 
</dependency> 
8

चेक पहले अपने वर्ग लोडर:

public static void main(String args[]) { 
    String relativeFilePath = "style/someCSSFile.css"; 
    String zipFilePath = "/someDirectory/someWarFile.war"; 
    String contents = readZipFile(zipFilePath,relativeFilePath); 
    System.out.println(contents); 
} 

public static String readZipFile(String zipFilePath, String relativeFilePath) { 
    try { 
     ZipFile zipFile = new ZipFile(zipFilePath); 
     Enumeration<? extends ZipEntry> e = zipFile.entries(); 

     while (e.hasMoreElements()) { 
      ZipEntry entry = (ZipEntry) e.nextElement(); 
      // if the entry is not directory and matches relative file then extract it 
      if (!entry.isDirectory() && entry.getName().equals(relativeFilePath)) { 
       BufferedInputStream bis = new BufferedInputStream(
         zipFile.getInputStream(entry)); 
       // Read the file 
        // With Apache Commons I/O 
       String fileContentsStr = IOUtils.toString(bis, "UTF-8"); 

        // With Guava 
       //String fileContentsStr = new String(ByteStreams.toByteArray(bis),Charsets.UTF_8); 
       // close the input stream. 
       bis.close(); 
       return fileContentsStr; 
      } else { 
       continue; 
      } 
     } 
    } catch (IOException e) { 
     logger.error("IOError :" + e); 
     e.printStackTrace(); 
    } 
    return null; 
} 

इस उदाहरण मैं उपयोग कर रहा हूँ अपाचे कॉमन्स मैं/हे और अगर आप Maven यहाँ उपयोग कर रहे हैं निर्भरता है।

ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 

if (classLoader == null) { 
    classLoader = Class.class.getClassLoader(); 
} 

classLoader.getResourceAsStream("xmlFileNameInJarFile.xml"); 

// xml file location at xxx.jar 
// + folder 
// + folder 
// xmlFileNameInJarFile.xml 
0

बस पूर्णता के लिए, वहाँ हाल ही में Jython मेलिंग सूची जहां जवाब में से एक इस सूत्र के लिए भेजा पर एक question किया गया है।

PythonInterpreter.execfile(InputStream) 
:

सवाल यह है कि Python स्क्रिप्ट है जो Jython के भीतर से एक .jar फ़ाइल में निहित है कॉल करने के लिए, सुझाव दिया जवाब ("InputStream" के साथ इस प्रकार के रूप में ऊपर जवाब में से एक में विस्तार से बताया है था

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