জারের মধ্যে থেকে একটি রিসোর্স ফাইল পড়া


242

আমি আমার জারের মধ্যে থেকে এমন একটি উত্স পড়তে চাই:

File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferredReader reader = new BufferedReader(new FileReader(file));

//Read the file

এবং এটি એક્લિপসে চলাকালীন ঠিকঠাক কাজ করে, তবে আমি যদি এটি চালাতে চালাতে রফতানি করি তবে এটি একটি অবৈধআর্গুমেন্ট এক্সেকশন রয়েছে:

Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical

এবং কেন আমি সত্যিই জানি না তবে কিছু পরিবর্তন করে আমি বদলেছি কিনা তা খুঁজে পেয়েছি

file = new File(getClass().getResource("/file.txt").toURI());

প্রতি

file = new File(getClass().getResource("/folder/file.txt").toURI());

তারপরে এটি বিপরীতে কাজ করে (এটি জারে কাজ করে তবে গ্রহন নয়)।

আমি Eclipse ব্যবহার করছি এবং আমার ফাইল সহ ফোল্ডারটি একটি ক্লাস ফোল্ডারে রয়েছে।


আপনি যদি কোনও ডিরেক্টরিতে ফাইলের জন্য কোনও সংখ্যার
জারির

1
আমি নিশ্চিত নই যে মূল প্রশ্নটি বসন্তের সাথে জড়িত ছিল। পূর্ববর্তী মন্তব্যে লিঙ্কটি একটি ভিন্ন প্রশ্ন থেকে একটি স্প্রিং নির্দিষ্ট উত্তর বোঝায়। আমি বিশ্বাস করি getResourceAsStreamএখনও সমস্যার একটি সহজ এবং বহনযোগ্য সমাধান।
ড্র ম্যাকইনিস

উত্তর:


398

বরং উত্স হিসাবে সম্বোধন করার চেষ্টা করা ফাইল শুধু জিজ্ঞাসা ClassLoader একটি ফিরতে InputStream মাধ্যমে পরিবর্তে রিসোর্সে getResourceAsStream :

InputStream in = getClass().getResourceAsStream("/file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

যতক্ষণ file.txtরিসোর্স ক্লাসপথে পাওয়া যায় ততক্ষণ এই পদ্ধতির একই পদ্ধতিতে কাজ করা হবে নির্বিশেষে রিসোর্সটি ডিরেক্টরিতে রয়েছে বা এ এর file.txtমধ্যে ।classes/jar

URI is not hierarchicalঘটে কারণ একটি বয়াম ফাইল মধ্যে একটি রিসোর্সে কোনো URI ভালো চেহারা কিছু যাচ্ছে: file:/example.jar!/file.txt। আপনি কোনও jar(একটি zipফাইল) এর মধ্যে এন্ট্রিগুলি পড়তে পারবেন না এটি প্লেইন পুরানো ফাইলের মতো

উত্তরগুলির মাধ্যমে এটি ভালভাবে ব্যাখ্যা করা হয়েছে:


3
আপনাকে ধন্যবাদ, এটি খুব সহায়ক ছিল এবং কোডটি পুরোপুরি কার্যকর করে, তবে আমার একটি সমস্যা আছে, আমার উপস্থিতি আছে কিনা তা নির্ধারণ করা দরকার InputStream(যেমন File.exists()) তাই আমার গেমটি ডিফল্ট ফাইলটি ব্যবহার করতে হবে কিনা তা বলতে পারে। ধন্যবাদ।
প্রিন্সসিজেসি

1
ওহ এবং বিটিডব্লিউ এর getClass().getResource("**/folder**/file.txt")কাজটি করার কারণটি কারণ আমার ফর্মটি আমার জারের মতো একই ডিরেক্টরিতে ছিল :)।
প্রিন্সসিজেসি

5
getResourceAsStreamযদি রিসোর্সটি না থাকে তবে তা বাতিল করে দেয় যাতে এটি আপনার "বিদ্যমান" পরীক্ষা হতে পারে।
ড্র ম্যাকইনিনিস

1
বিটিডাব্লু, আপনার একটি টাইপ রয়েছে: এটি বাফারড্রেডার হওয়া উচিত, বাফারড্রেডার নয় (পরে অতিরিক্ত 'আর' লক্ষ্য করুন)
মেলমাইন্ডলিন

2
এবং অবশ্যই ... ভুলবেন না inputStream এবং BufferedReader বন্ধ করতে
Noremac

26

একটি পাত্রে কোনও ফাইল অ্যাক্সেস করতে আপনার কাছে দুটি বিকল্প রয়েছে:

  • আপনার প্যাকেজের নামের সাথে মেলে ডিরেক্টরি কাঠামোতে ফাইলটি রাখুন (.jar ফাইলটি বের করার পরে, এটি .class ফাইলের মতো একই ডিরেক্টরিতে হওয়া উচিত), তারপরে এটি ব্যবহার করে অ্যাক্সেস করুন getClass().getResourceAsStream("file.txt")

  • রুটটি ফাইলটি রাখুন (.jar ফাইলটি বের করার পরে, এটি রুটে হওয়া উচিত), তারপরে এটি ব্যবহার করে অ্যাক্সেস করুন Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")

যখন জারটি প্লাগইন হিসাবে ব্যবহৃত হয় তখন প্রথম বিকল্পটি কাজ করতে পারে না।


এই দুর্দান্ত উত্তরের জন্য আপনাকে অনেক ধন্যবাদ ... দ্বিতীয় বিকল্পের আরেকটি সুবিধা হ'ল এটি মূল পদ্ধতি থেকেও কাজ করে, কারণ getClass () কেবল স্থিতিশীল পদ্ধতি থেকে নয় একটি উদাহরণ থেকে কাজ করে।
ড্যান অরটেগা

6

আমার আগে এই সমস্যা ছিল এবং আমি লোডিংয়ের জন্য ফ্যালব্যাকের পথ তৈরি করি। মূলত প্রথম পথে .jar ফাইলের মধ্যে কাজ করা হয় এবং দ্বিতীয় উপায়টি গ্রহন বা অন্যান্য IDE এর মধ্যে কাজ করে।

public class MyClass {

    public static InputStream accessFile() {
        String resource = "my-file-located-in-resources.txt";

        // this is the path within the jar file
        InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource);
        if (input == null) {
            // this is how we load file within editor (eg eclipse)
            input = MyClass.class.getClassLoader().getResourceAsStream(resource);
        }

        return input;
    }
}

3

এখন অবধি (ডিসেম্বর 2017), আমি একমাত্র সমাধানটি খুঁজে পেয়েছি যা আইডিই এর ভিতরে এবং বাইরে উভয়ই কাজ করে

প্যাথম্যাচিংআরসোর্সপ্যাটার্ন রিসোলভার ব্যবহার করুন

দ্রষ্টব্য: এটি বসন্ত-বুটেও কাজ করে

এই উদাহরণে আমি src / প্রধান / সংস্থানসমূহ / আমার_ফোল্ডারে অবস্থিত কিছু ফাইল পড়ছি :

try {
    // Get all the files under this inner resource folder: my_folder
    String scannedPackage = "my_folder/*";
    PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
    Resource[] resources = scanner.getResources(scannedPackage);

    if (resources == null || resources.length == 0)
        log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
    else {
        for (Resource resource : resources) {
            log.info(resource.getFilename());
            // Read the file content (I used BufferedReader, but there are other solutions for that):
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                // ...
                // ...                      
            }
            bufferedReader.close();
        }
    }
} catch (Exception e) {
    throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
}

3

সমস্যাটি হ'ল নির্দিষ্ট তৃতীয় পক্ষের গ্রন্থাগারগুলিতে ইনপুট স্ট্রিমের পরিবর্তে ফাইলের প্যাথনাম প্রয়োজন। উত্তরগুলির বেশিরভাগই এই সমস্যাটির সমাধান করে না।

এই ক্ষেত্রে, একটি কাজ হ'ল সংস্থানীয় ফাইলটিতে সংস্থান বিষয়বস্তু অনুলিপি করা। নিম্নলিখিত উদাহরণ jUnit ব্যবহার করে TemporaryFolder

    private List<String> decomposePath(String path){
        List<String> reversed = Lists.newArrayList();
        File currFile = new File(path);
        while(currFile != null){
            reversed.add(currFile.getName());
            currFile = currFile.getParentFile();
        }
        return Lists.reverse(reversed);
    }

    private String writeResourceToFile(String resourceName) throws IOException {
        ClassLoader loader = getClass().getClassLoader();
        InputStream configStream = loader.getResourceAsStream(resourceName);
        List<String> pathComponents = decomposePath(resourceName);
        folder.newFolder(pathComponents.subList(0, pathComponents.size() - 1).toArray(new String[0]));
        File tmpFile = folder.newFile(resourceName);
        Files.copy(configStream, tmpFile.toPath(), REPLACE_EXISTING);
        return tmpFile.getAbsolutePath();
    }

এটি অনেক কিছুই দ্বারা প্রদর্শিত হয়। এটি দলিল করার জন্য ধন্যবাদ। আমি কৌতূহলী যে জুনিত ছাড়া অন্য বিকল্পগুলি কী আছে।
অ্যালেক্স মুর-নিমি

0

আপনি যদি ফাইল হিসাবে পড়তে চান তবে আমার বিশ্বাস এখনও একই রকম সমাধান রয়েছে:

    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("file/test.xml").getFile());

4
URL.getFile () কোনও ইউআরএল কোনও ফাইলের নামে রূপান্তর করে না । এটি হোস্টের পরে সমস্ত শতাংশ-এনকোডিং অক্ষত রেখে URL এর অংশটি ফেরত দেয়, সুতরাং যদি পাথটিতে কোনও নন-এসএসআইআই অক্ষর বা কোনও এএসসিআইআই অক্ষর থাকে তবে ইউআরএলগুলিতে অনুমতি নেই (স্পেস সহ) ফলাফলটি কোনও ফাইলের নাম হবে না , এমনকি যদি URL টি file:URL থাকে।
ভিজিআর

48
প্রোগ্রামটি একবার জারে তৈরি হয়ে গেলে এটি ভিতরে কাজ করে না
অক্ষয় কাসার

1
আপনি স্ট্রিংতে রূপান্তর না করে এবং স্থানীয়ভাবে স্থানীয়ভাবে সংরক্ষণ না করা পর্যন্ত জার থেকে কাজ করে না।
smoosh911

0

আপনি সঠিক বিভাজক সঙ্গে কাজ করে তা নিশ্চিত করুন। আমি /একটি সাথে একটি আপেক্ষিক পথে সমস্ত প্রতিস্থাপন File.separator। এটি আইডিইতে দুর্দান্ত কাজ করেছে, তবে জেআর বিল্ডে কাজ করেনি।


0

আমি মনে করি এটি জাভাতেও কাজ করা উচিত। নিম্নলিখিত কোডগুলি আমি ব্যবহার করছি কোটলিন ব্যবহার করা।

val resource = Thread.currentThread().contextClassLoader.getResource('resources.txt')

0

আমি একটি সমাধান পেয়েছি

BufferedReader br = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream(path)));

"মেইন" টি জাভা ক্লাসের সাথে প্রতিস্থাপন করুন যা আপনি কোড করেছেন।

উদাহরণস্বরূপ, যদি আপনি com.issac.state প্যাকেজটিতে State1.txt রাখেন, তবে আপনি লিনাক্স বা ম্যাক চালনা করলে পাথটি "/ com / ইস্যাক / রাষ্ট্র / রাজ্য 1" হিসাবে টাইপ করুন। আপনি যদি উইন্ডোজ চালনা করেন তবে "\ com \ ইস্যুক \ রাষ্ট্র \ রাজ্য 1" হিসাবে পাথটি টাইপ করুন। ফাইলটি ব্যতিক্রম না ঘটলে ফাইলটিতে .txt এক্সটেনশনটি যুক্ত করবেন না।


-1

আপনি শ্রেণি লোডার ব্যবহার করতে পারেন যা ক্লাসপথ থেকে মূল পথ হিসাবে পড়বে (শুরুতে "/" ছাড়াই)

InputStream in = getClass().getClassLoader().getResourceAsStream("file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

-1

আপনি যদি বসন্ত ব্যবহার করছেন তবে src / প্রধান / সংস্থান থেকে ফাইল পড়তে আপনি নিম্নলিখিত পদ্ধতিটি ব্যবহার করতে পারেন:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.core.io.ClassPathResource;

  public String readFileToString(String path) throws IOException {

    StringBuilder resultBuilder = new StringBuilder("");
    ClassPathResource resource = new ClassPathResource(path);

    try (
        InputStream inputStream = resource.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {

      String line;

      while ((line = bufferedReader.readLine()) != null) {
        resultBuilder.append(line);
      }

    }

    return resultBuilder.toString();
  }

1
এসও আপনাকে স্বাগতম। এটি প্রশ্নের উত্তর দেয় না। আপনার যথেষ্ট খ্যাতি অর্জনের পরে আপনি যে কোনও পোস্টে মন্তব্য করতে সক্ষম হবেন । পরিবর্তে আমি কি করতে পারি তা এটি পরীক্ষা করে দেখুন
ওয়েওওয়েওয়ের

এটি ফাইলের লাইন ব্রেকগুলি সরিয়ে ফেলবে!
elad.chen

-1

কিছু কারণে classLoader.getResource()সবসময় নাল ফিরে যখন আমি WildFly থেকে 14 ওয়েব অ্যাপ্লিকেশন মোতায়েন থেকে classLoader পেয়ে getClass().getClassLoader()বা Thread.currentThread().getContextClassLoader()আয় নাল।

getClass().getClassLoader() এপিআই ডক বলেছেন,

"ক্লাসের জন্য শ্রেণি লোডার ফিরিয়ে দেয় Some কিছু বাস্তবায়ন বুটস্ট্র্যাপ শ্রেণীর লোডার উপস্থাপন করতে শূন্য ব্যবহার করতে পারে class

আপনি যদি ওয়াইল্ডফ্লাই ব্যবহার করছেন এবং আপনার ওয়েব অ্যাপ্লিকেশনটি চেষ্টা করে দেখুন

request.getServletContext().getResource()রিসোর্স ইউআরএল ফিরিয়ে দিয়েছে। এখানে অনুরোধ হ'ল সার্ভলেটরেখেষ্টের একটি বিষয়।


-2

নীচে কোডটি স্প্রিং বুট (কোটলিন) এর সাথে কাজ করে:

val authReader = InputStreamReader(javaClass.getResourceAsStream("/file1.json"))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.