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"

এই কাজগুলির কোনোটাই নয়। আমি এখন পর্যন্ত এই বিষয়টিতে অসংখ্য প্রশ্ন পড়েছি , তবে তাদের কোনওটিই সহায়ক হয়নি - সাধারণত, তারা কেবল মূল পথ ব্যবহার করে ফাইলগুলি লোড করতে বলে, যা আমি ইতিমধ্যে করছি। এটি, বা কেবল বর্তমান ডিরেক্টরি থেকে ফাইলটি লোড করুন (স্রেফ লোড filename), যা আমি চেষ্টা করেছি। ফাইলটি উপযুক্ত নাম সহ উপযুক্ত স্থানে জেআর-এ সংকলিত হচ্ছে।

আমি কীভাবে এটি সমাধান করব?


3
আপনি চেক করা যে এটা সত্যিই আছে হয় বয়াম ফাইলে? আপনি ফাইল কেসিং পরীক্ষা করেছেন?
জন স্কিটি

@ জনস্কিট এটি যথাযথ স্থানে জার ফাইলটিতে সংকলন করা হচ্ছে, এবং কেসটি সঠিক।

1
@greedybuddha যদিও আমি স্থির প্রসঙ্গ থেকে এটি প্রার্থনা করতে পারি না, আমি এটি ব্যবহার করে প্রার্থনা করতে পারি Lifepaths.class। বলা হচ্ছে, কেন getClassLoader()এটি কাজ করতে দেয়? (এছাড়াও, একটি উত্তর পোস্ট করতে নির্দ্বিধায় বোধ করুন!)

দেখাতে পারবেন Lifepaths.getClass()? অবজেক্টে এই জাতীয় কোনও স্থিতিশীল পদ্ধতি নেই ...
পুস

1
এই উত্তরটি দেখুন এবং আপনি এটি ব্যবহার করে এটি পেতে পারেন কিনা তা দেখুন getResource(String)। বিটিডাব্লু - আমার যেসব staticপ্রসঙ্গে কাজ করতে হবে সে সম্পর্কে আমার সবসময় সমস্যা ছিল । সমস্যাটি মূলত যে প্রাপ্ত বর্গ লোডারটি জে 2 এস ক্লাসের জন্য তৈরি করা হয়। আপনার প্রসঙ্গ শ্রেণীর লোডার অ্যাক্সেস করা দরকার যা অ্যাপ্লিকেশনটির জন্য তৈরি।
অ্যান্ড্রু থম্পসন

উত্তর:


158

Lifepaths.class.getClass().getResourceAsStream(...) সিস্টেম বর্গ লোডার ব্যবহার করে রিসোর্সগুলি লোড করে, এটি স্পষ্টভাবে ব্যর্থ হয় কারণ এটি আপনার জআরগুলি দেখতে পায় না

Lifepaths.class.getResourceAsStream(...) Lifepaths শ্রেণিতে লোড করা একই শ্রেণীর লোডার ব্যবহার করে সংস্থানগুলি লোড করে এবং এটি আপনার জেআর-এ সংস্থানসমূহের অ্যাক্সেস থাকা উচিত


128
কেবল যোগ করার জন্য, getResourceAsStream (নাম) চালু করার সময়, নামটি অবশ্যই "/" দিয়ে শুরু করা উচিত। এটি প্রয়োজনীয় কিনা আমি নিশ্চিত নই, তবে এটি ছাড়া আমার সমস্যা আছে have
ডেভিড

3
আমি আজ / গতকাল সকাল 8 টা থেকে এই নিয়ে স্ক্রু দিচ্ছি। আমাকে বাঁচিয়েছে এটি কাজ করতে আমারও একটি শীর্ষস্থানীয় স্ল্যাশ দরকার ছিল need
কাইল

4
এছাড়াও মনে রাখবেন যে কাঙ্ক্ষিত উত্স প্যাকেজ শ্রেণিবদ্ধের বাইরে থাকতে পারে। এক্ষেত্রে আপনাকে আপনার স্তরে "../" ব্যবহার করতে হবে আপনার উত্সটিতে পৌঁছানোর জন্য একটি স্তর এবং তারপরে নীচে অন্য পাথ শাখায় যেতে হবে।
জোন

3
@ ডেভিড - আমি মনে করি এটি (নেতৃত্বাধীন '/') প্রয়োজনীয় নয় অন্যথায় এটি লাইফপথস ক্লাস প্যাকেজটির সাথে সম্পর্কিত হয়

5
কিছু তথ্য যুক্ত করতে, /আপনার ফাইলটি যদি কোনও ভিন্ন ডিরেক্টরিতে থাকে তবে আপনাকে আপনার পাথের আগে একটি যুক্ত করতে হবে ; উদাহরণস্বরূপ initialization/Lifepaths.txt। যদি ফাইলের পথটি আপনার শ্রেণির একই হয় (তবে মূল dir হিসাবে সম্পদের অধীনে) আপনি কেবল কোনও ফাইলের নাম রাখতে পারেন /। উদাহরণস্বরূপ যদি আপনার শ্রেণীর নিম্নলিখিত পথ থাকে তবে src/main/java/paths/Lifepaths.javaআপনার ফাইলটির এই পথটি থাকতে হবে src/main/resources/paths/Lifepaths.txt
ডিভিউইজ

59

নিয়মগুলি নিম্নরূপ:

  1. আপনি জারের অভ্যন্তরে যে ফাইলটি লোড করতে চান তার অবস্থান পরীক্ষা করুন (এবং এটি অবশ্যই জেআর-এ যুক্ত হয়েছে তা নিশ্চিত করুন)
  2. হয় একটি নিখুঁত পাথ ব্যবহার করুন: পথটি JAR এর মূল থেকে শুরু হয়
  3. আপেক্ষিক পথটি ব্যবহার করুন: আপনি যে ক্লাসটি getResource / getResoucreAsStream বলছেন তার প্যাকেজ ডিরেক্টরিতে পথ শুরু হয়

এবং চেষ্টা কর:

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

পরিবর্তে

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

(কোনও পার্থক্য হয়েছে কিনা তা নিশ্চিত নন তবে পূর্ববর্তী সঠিক ক্লাসলোডার / জেআর ব্যবহার করবেন, যদিও আমি পরবর্তীটির সাথে নিশ্চিত নই)


2
আমি ইতিমধ্যে এই তিনটি জিনিস সম্পন্ন করেছি। আমার প্রশ্নটি আবার পড়ুন।

আপনার প্রশ্ন থেকে এটি পরিষ্কার নয় যে "প্রাসঙ্গিক ডিরেক্টরি কাঠামো "টি কী এবং আপনি যদি ফাইলটি জেআর (পদক্ষেপ 1) এ অবস্থিত কিনা তা সত্যই যাচাই করেছেন
পুস

1
আপেক্ষিক পথ সম্পর্কে আপনার মন্তব্য শেষ পর্যন্ত আমার সমস্যার সমাধান করেছে; ধন্যবাদ!
পল বর্ম্যানস

মজাদার. দেখা যাচ্ছে যে আমি এটি পেতে "/config.properties" (একটি স্ল্যাশ সহ) করতে হয়েছিল ...
এর্ক

45

সুতরাং একটি জার থেকে কোনও সংস্থান গ্রহণ করার বিভিন্ন উপায় রয়েছে এবং প্রত্যেকটির কিছুটা আলাদা বাক্য গঠন রয়েছে যেখানে পাথটি আলাদাভাবে নির্দিষ্ট করা দরকার।

আমি যা দেখেছি তার সেরা ব্যাখ্যাটি জাভা ওয়ার্ল্ডের এই নিবন্ধটি । আমি এখানে সংক্ষিপ্ত করব, তবে আপনি যদি আরও জানতে চান তবে আপনার নিবন্ধটি পরীক্ষা করা উচিত।

পদ্ধতি

1) ClassLoader.getResourceAsStream()

ফর্ম্যাট: "/" - পৃথক নাম; কোন শীর্ষস্থানীয় "/" (সমস্ত নামই নিখুঁত)।

উদাহরণ: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

2) Class.getResourceAsStream()

ফর্ম্যাট: "/" - পৃথক নাম; শীর্ষস্থানীয় "/" নিখুঁত নাম নির্দেশ করে; অন্যান্য সমস্ত নাম শ্রেণীর প্যাকেজের সাথে সম্পর্কিত

উদাহরণ: this.getClass().getResourceAsStream("/some/pkg/resource.properties");


আপনার দ্বিতীয় উদাহরণটি ভাঙা হয়েছে
জানুস ট্রয়লসন

1
দ্বিতীয় উদাহরণটি ভাঙ্গা হয়নি, কারণ আমি উত্তরে বলেছি এটি কোথায় সংস্থান রয়েছে তার উপর নির্ভর করে।
লোভীবুদ্ধি

এছাড়াও: আপনার আইডিই উত্স ফোল্ডারটি রিফ্রেশ করে ফাইলটি ('কিছু / পিকেজি / রিসোর্স.প্রোপার্টি') দেখেছেন তা নিশ্চিত করুন।
এরিক ডুমিনিল

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(); 

আমার একবার অনুরূপ প্রশ্ন ছিল: জার থেকে টেক্সট ফাইল পড়া ব্যর্থ হয় তবে চিত্রটি পড়া কাজ করে


3
getResourceAsStream () ঠিক ঠিক এটাই করে
ফেডারেশন

8

আপনি যে ক্লাসলুডারটি ব্যবহার করছেন তাতে সমস্যা রয়েছে বলে মনে হচ্ছে। শ্রেণি লোড করতে প্রসঙ্গক্লাসলুডার ব্যবহার করুন। এটি স্থিতিশীল / অ-স্থিত পদ্ধতিতে তা নির্বিশেষে is

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


5

আমি নিজেকে একটি অনুরূপ ইস্যুতে খুঁজে পেয়েছি। যেহেতু আমি maven ব্যবহার করছি তখন আমার এই জাতীয় কিছু অন্তর্ভুক্ত করার জন্য আমার pom.xML আপডেট করতে হবে:

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

সেই ফোল্ডারটি কোথায় রয়েছে তা নির্দিষ্ট করার জন্য সেখানে উত্স ট্যাগটি নোট করুন। যদি আপনার প্রকল্পগুলি নেস্টেড থাকে (যেমন আমি করি) তবে আপনি যে মডিউলটিতে কাজ করছেন তার পরিবর্তে আপনি অন্যান্য অঞ্চল থেকে সংস্থান পেতে চাইতে পারেন This যদি আপনি অনুরূপ কনফিগার ডেটা ব্যবহার করেন তবে প্রতিটি রেপোতে একই ফাইলটি কমিয়ে আনতে সহায়তা করে


3

আমার জন্য যা কাজ করেছিল তা হ'ল ফাইলটি যুক্ত করা My Project/Java Resources/srcএবং তারপরে ব্যবহার করা

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

আমার এই ফাইলটিকে সুস্পষ্টভাবে পথে যুক্ত করার /srcদরকার নেই (এটি এটিকে স্পষ্টতই যুক্ত করা দরকার)


ভুল জাভা সিনট্যাক্স
ইলিয়া খারলামভ

2

সহায়তার কথা জানুন না তবে আমার ক্ষেত্রে আমার / / src / ফোল্ডারে আমার সংস্থান ছিল এবং এই ত্রুটিটি পাচ্ছিলাম। আমি তখন ছবিটিকে বিন ফোল্ডারে সরিয়ে নিয়েছি এবং এটি সমস্যার সমাধান করেছে।


2

আপনার উত্স ডিরেক্টরি (যেমন "src") আপনার শ্রেণিপথে রয়েছে তা নিশ্চিত করুন (এটি নিশ্চিত করুন যে এটি আপনার গ্রহণের পথে নির্মানের পথে উত্স ডিরেক্টরি)।

নিশ্চিত হয়ে নিন যে ক্লাসটি প্রধান ক্লাসলোডার থেকে লোড হয়েছে।

তারপরে, src / সূচনা / Lifepaths.txt লোড করতে, ব্যবহার করুন

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

কেন: ক্লাজের ক্লাসপাঠের মধ্যে থেকেই ক্লাবের ক্লাসপাঠের মধ্যেclazz.getResourcesAsStream(foo) থেকে ফু দেখা যাচ্ছে , ক্লাজের ডিরেক্টরিতে বাস করে । শীর্ষস্থানীয় "/" এটিকে ক্লাজের ক্লাসপথের যে কোনও ডিরেক্টরিের গোড়া থেকে লোড করে।

টমক্যাটের মতো আপনি যদি কোনও ধরণের ধারক না হয়ে থাকেন বা সরাসরি ক্লাসলয়েডারদের সাথে কিছু করেন না তবে আপনি কেবল আপনার গ্রহন / কমান্ড লাইনের ক্লাসপাথকে একমাত্র ক্লাসলোডার ক্লাসপাথ হিসাবে বিবেচনা করতে পারেন।


2

ডিফল্ট জেভিএম ক্লাস লোডার প্রথমে সংস্থানগুলি লোড করতে প্যারেন্ট-ক্লাসলোডার ব্যবহার করবে: deletegate পিতা বা মাতা-classloader

Lifepaths.class.getClass()এর ক্লাসলোডারটি হ'ল bootstrap classloader, তাই getResourceAsStreamব্যবহারকারী প্রদত্ত নির্বিশেষে কেবল $ জাভাহোম হোম অনুসন্ধান করবেclasspath । স্পষ্টতই, Lifepaths.txt নেই।

Lifepaths.classএর ক্লাসলোডারটি system classpath classloaderতাই getResourceAsStreamব্যবহারকারী-সংজ্ঞায়িত classpathএবং লাইফপ্যাথস.টেক্সট সেখানে অনুসন্ধান করবে ।

ব্যবহার করার সময় 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

আপনার যা সত্যই দরকার তা হ'ল ফাইলের জন্য সম্পূর্ণ পরম শ্রেণিপথ। সুতরাং এটি অনুমান করার পরিবর্তে, রুটটি অনুসন্ধান করার চেষ্টা করুন এবং তারপরে ফাইলটিকে আরও ভাল অবস্থানের একটি <.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

@ এমরাকুল ... আমি আপনাকে একটি বিকল্প পরামর্শ দেব যেহেতু আপনি একটি * .txt ফাইল লোড করার চেষ্টা করছেন বলে মনে হচ্ছে। FileInputStream()বরং এই বিরক্তিকর getClass().getClassLoader().getResourceAsStream()বা ব্যবহার করা ভাল getClass().getResourceAsStream()। কমপক্ষে আপনার কোডটি সঠিকভাবে কার্যকর হবে।


কি ??? এই ধরনের কাজের উত্তরের জন্য -1। যেভাই হোকনা কেন. তবে উপরের প্রস্তাবিত সমাধানটি অবশ্যই কাজ করবে।
জৈন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.