जार के अंदर फ़ाइल वसंत के लिए दिखाई नहीं दे रही है


104

सब

मैंने निम्नलिखित MANIFEST.MF के साथ एक जार फ़ाइल बनाई:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.6.0_25-b06 (Sun Microsystems Inc.)
Main-Class: my.Main
Class-Path: . lib/spring-core-3.2.0.M2.jar lib/spring-beans-3.2.0.M2.jar

इसकी जड़ में my.config नामक एक फाइल है जो मेरे स्प्रिंग-संदर्भ में संदर्भित है। xml:

<bean id="..." class="...">
    <property name="resource" value="classpath:my.config" />
</bean>

अगर मैं जार चलाता हूं, तो सब कुछ ठीक लग रहा है, उस विशिष्ट फ़ाइल को लोड करने के लिए:

Caused by: java.io.FileNotFoundException: class path resource [my.config] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/D:/work/my.jar!/my.config
        at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:205)
    at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
    at eu.stepman.server.configuration.BeanConfigurationFactoryBean.getObject(BeanConfigurationFactoryBean.java:32)
    at eu.stepman.server.configuration.BeanConfigurationFactoryBean.getObject(BeanConfigurationFactoryBean.java:1)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
    ... 22 more
  • कक्षाओं को जार के अंदर से लोड किया जाता है
  • वसंत और अन्य निर्भरताएं अलग-अलग जार से भरी हुई हैं
  • वसंत संदर्भ लोड किया गया है (नया ClassPathXmlApplicationContext ("स्प्रिंग-संदर्भ / ApplicationContext.xml"))
  • my.properties को प्रॉपर्टीहोल्डरकॉन्फिगरर ("classpath: my.properties") में लोड किया गया है
  • अगर मैं अपनी .config फ़ाइल को फ़ाइल सिस्टम के बाहर रखता हूँ, और संसाधन url को 'फ़ाइल:' में बदल देता हूँ, तो सब कुछ लगता है ...

कोई सुझाव?

जवाबों:


211

यदि आपकी स्प्रिंग-संदर्भ। Xml और my.config फाइलें अलग-अलग जार में हैं, तो आपको उपयोग करने की आवश्यकता होगी classpath*:my.config?

अधिक जानकारी यहाँ

इसके अलावा, सुनिश्चित करें कि आप जार फ़ाइल के अंदर से लोड करते समय उपयोग resource.getInputStream()नहीं कर रहे हैं resource.getFile()


1
वे एक ही जार में हैं, लेकिन मैंने एक ही परिणाम के साथ आपके समाधान की कोशिश की: java.io.FileNotFoundException: क्लास पाथ रिसोर्स [classpath *: my.config] को URL में हल नहीं किया जा सकता क्योंकि यह मौजूद नहीं है
BTakacs

14
फिर से देखते हुए, आपके कुछ कॉलिंग कोड (संभवतः बीनकोफिगरेशन फैक्ट्रीबीन) एक java.io.File को लोड करने की कोशिश कर रहे हैं। फाइल फाइल सिस्टम पर फाइलों को संदर्भित करता है, जो एक जार में प्रविष्टियां नहीं हैं। कॉलिंग कोड को जार से बाहर लोड करने के बजाय रिसोर्स.गेटइन्पुटस्ट्रीम का उपयोग करना चाहिए।
sbk

58
... और यह जवाब है ... धन्यवाद! एक जार के अंदर
रिसोर्स.गेट फ़ाइल

2
कोई भी मौका एक "क्यों?" एक जार के अंदर getFile () का उपयोग नहीं करने के पीछे? क्या यह सिर्फ इतना है कि फ़ाइल जार के अंदर है और इसलिए "फ़ाइल" जार फ़ाइल है ??
रॉकमेटहार्डप्लेस

8
बस। Java.io.File एक निर्देशिका संरचना में फ़ाइल सिस्टम पर एक फ़ाइल का प्रतिनिधित्व करता है। जार एक java.io.File है। लेकिन उस फ़ाइल के भीतर कुछ भी java.io.File की पहुंच से परे है। जहाँ तक जावा का संबंध है, जब तक कि यह असम्पीडित न हो, जार फ़ाइल में एक वर्ग शब्द दस्तावेज़ में एक शब्द से अलग नहीं है।
sbk

50

मुझे पता है कि इस सवाल का जवाब पहले ही दिया जा चुका है। हालाँकि, स्प्रिंग बूट का उपयोग करने वालों के लिए, इस लिंक ने मेरी मदद की - https://smarterco.de/java-load-file-classpath-spring-boot/

हालाँकि, resourceLoader.getResource("classpath:file.txt").getFile();इस समस्या के कारण और sbk की टिप्पणी थी:

बस। एक java.io.File एक निर्देशिका संरचना में फ़ाइल सिस्टम पर एक फ़ाइल का प्रतिनिधित्व करता है। जार एक java.io.File है। लेकिन उस फ़ाइल के भीतर कुछ भी java.io.File की पहुंच से परे है। जहाँ तक जावा का संबंध है, जब तक कि यह असम्पीडित न हो, जार फ़ाइल में एक वर्ग शब्द दस्तावेज़ में एक शब्द से अलग नहीं है।

मुझे यह समझने में मदद की कि इसका उपयोग क्यों करना है getInputStream()। यह अब मेरे लिए काम करता है!

धन्यवाद!


38

वसंत जार पैकेज में, मैं नया प्रयोग करता हूं ClassPathResource(filename).getFile(), जो अपवाद को फेंकता है:

इसे पूर्ण फ़ाइल पथ पर हल नहीं किया जा सकता क्योंकि यह फ़ाइल सिस्टम में नहीं रहता है: जार

लेकिन नए प्रयोग से ClassPathResource(filename).getInputStream()यह समस्या दूर हो जाएगी। कारण यह है कि जार में कॉन्फ़िगरेशन फ़ाइल ऑपरेटिंग सिस्टम के फ़ाइल ट्री में मौजूद नहीं है, इसलिए इसका उपयोग करना चाहिए getInputStream()


2

Tomcat6.x का उपयोग करते समय मुझे ऐसी ही समस्या थी और मुझे जो भी सलाह मिली, उनमें से कोई भी मदद नहीं कर रहा था। आखिर में मैंने डिलीट कर दियाwork फ़ोल्डर को (टॉमकैट का) और समस्या चली गई।

मुझे पता है कि यह अतार्किक है लेकिन प्रलेखन उद्देश्य के लिए ...


1

@Sbk का उत्तर यह है कि हमें इसे स्प्रिंग-बूट वातावरण में करना चाहिए (इसके अलावा @Value ("$ {classpath *:})), मेरी राय में। लेकिन मेरे परिदृश्य में यह तब काम नहीं कर रहा था जब स्टैंडअलोन पर अमल होता। jar..may be I कुछ गलत किया।

लेकिन यह ऐसा करने का एक और तरीका हो सकता है,

InputStream is = this.getClass().getClassLoader().getResourceAsStream(<relative path of the resource from resource directory>);

1

मुझे एक समस्या अधिक जटिल लग रही थी क्योंकि मेरे पास एक ही नाम से एक से अधिक फ़ाइल हैं, एक मुख्य स्प्रिंग बूट जार में है और अन्य मुख्य वसा जार के अंदर जार में हैं। मेरा समाधान सभी संसाधनों को एक ही नाम से मिल रहा था और उसके बाद पैकेज नाम से फ़िल्टरिंग की आवश्यकता थी। सभी फाइलें प्राप्त करने के लिए:

ResourceLoader resourceLoader = new FileSystemResourceLoader();
final Enumeration<URL> systemResources = resourceLoader.getClassLoader().getResources(fileNameWithoutExt + FILE_EXT);

0

मैं अपने स्प्रिंग ऐप में संसाधन को पुन: लोड करने का एक मुद्दा बना रहा था, और पाया कि मुद्दा यह था कि मुझे इसका उपयोग करना चाहिए resource.getInputStream। यहाँ एक उदाहरण है जिसमें दिखाया गया है config/myfilesकि सभी फ़ाइलों में पुनरावृत्ति कैसे होती jsonहै।

Example.java

private String myFilesResourceUrl = "config/myfiles/**/";
private String myFilesResourceExtension = "json";

ResourceLoader rl = new ResourceLoader();

// Recursively get resources that match. 
// Big note: If you decide to iterate over these, 
// use resource.GetResourceAsStream to load the contents
// or use the `readFileResource` of the ResourceLoader class.
Resource[] resources = rl.getResourcesInResourceFolder(myFilesResourceUrl, myFilesResourceExtension);

// Recursively get resource and their contents that match. 
// This loads all the files into memory, so maybe use the same approach 
// as this method, if need be.
Map<Resource,String> contents = rl.getResourceContentsInResourceFolder(myFilesResourceUrl, myFilesResourceExtension);

ResourceLoader.java

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.StreamUtils;

public class ResourceLoader {
  public Resource[] getResourcesInResourceFolder(String folder, String extension) {
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    try {
      String resourceUrl = folder + "/*." + extension;
      Resource[] resources = resolver.getResources(resourceUrl);
      return resources;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public String readResource(Resource resource) throws IOException {
    try (InputStream stream = resource.getInputStream()) {
      return StreamUtils.copyToString(stream, Charset.defaultCharset());
    }
  }

  public Map<Resource, String> getResourceContentsInResourceFolder(
      String folder, String extension) {
    Resource[] resources = getResourcesInResourceFolder(folder, extension);

    HashMap<Resource, String> result = new HashMap<>();
    for (var resource : resources) {
      try {
        String contents = readResource(resource);
        result.put(resource, contents);
      } catch (IOException e) {
        throw new RuntimeException("Could not load resource=" + resource + ", e=" + e);
      }
    }
    return result;
  }
}

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