একটি জাভা জেআর ফাইলটিতে কোনও সংস্থার পাথ কীভাবে পাবেন


166

আমি একটি রিসোর্সের পথে যাওয়ার চেষ্টা করছি তবে আমার ভাগ্য হয়নি।

এটি (আইডিই এবং জেআর উভয় সহ) কাজ করে তবে এইভাবে আমি কোনও ফাইলের পথ পাচ্ছি না, কেবলমাত্র ফাইলের সামগ্রী:

ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));

আমি যদি এটি করি:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());

ফলাফল হলো: java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

কোনও রিসোর্স ফাইলে যাওয়ার কোনও উপায় আছে কি?


1
হ্যাঁ. আমি একটি ক্লাস পেয়েছি যা আমি উভয়ের সাথেই কাজ করতে চাই, বাইরের একটি ফোল্ডার (যদি আমি কনফিগার ফাইলের কিছু প্যারামিটার পরিবর্তন করতে চাই) এবং একটি জেআর যা ব্যবহারকারীর কাছে বাস্তবায়ন কনফিগারেশন ফাইলগুলি আড়াল করে (বিতরণযোগ্য হিসাবে) সমস্ত লোকের কাছে জেআর)।
No_ripcord

1
সুতরাং ক্লাসটি কেবল একটি ফাইল (কনফিগারেশন ফাইল) এ একটি প্যাথ পায়।
no_ripcord

3
তারপরে আপনার সম্ভবত কোনও ইনপুট স্ট্রিমের সাথে সেই শ্রেণি চুক্তি হওয়া উচিত, যা আপনি উভয় উত্স থেকে পেতে পারেন।
কার্ল ম্যানাস্টার

1
হ্যা আমি জানি. তবে এটি অন্যভাবে আরও পরিষ্কার এবং পরিষ্কার হত। তবে যাইহোক thx।
no_ripcord

1
আপনি কি এই প্রশ্নের বিকল্প # 4 এর মতো কিছু করার চেষ্টা করছেন? stackoverflow.com/questions/775389/…
এরিকসন

উত্তর:


71

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

Java.io.File পেয়ে আপনি যা কিছু করতে পারেন তা কোনও অস্থায়ী ফাইলটিতে স্ট্রিমটি অনুলিপি করে এবং একই রকম করা সম্ভব যদি জাভা.আইও.ফাইলে একেবারে প্রয়োজনীয় হয়।


6
আপনি যখন আপনার সংস্থানটি খোলার জন্য কল করেন তখন আপনি 'আরএসআরসি:' যুক্ত করতে পারেন। নতুন ফাইলের মতো ("আরএসসিআর: ফাইল নাম.txt") এটি ফাইলের
নাম.টিএসটিএসটি

63

কোনও সংস্থান লোড করার সময় আপনি এটির মধ্যে পার্থক্য লক্ষ্য করেছেন তা নিশ্চিত করুন:

getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path

এবং

getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning

আমার ধারণা, কোনও সংস্থান লোড করার সময় এই বিভ্রান্তি বেশিরভাগ সমস্যার সৃষ্টি করে।


এছাড়াও, আপনি যখন কোনও চিত্র লোড করছেন তখন এটি ব্যবহার করা সহজ getResourceAsStream():

BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));

যখন আপনাকে সত্যিই কোনও জআর সংরক্ষণাগার থেকে কোনও (অ-চিত্র) ফাইল লোড করতে হবে, আপনি এটি চেষ্টা করতে পারেন:

File file = null;
String resource = "/com/myorg/foo.xml";
URL res = getClass().getResource(resource);
if (res.getProtocol().equals("jar")) {
    try {
        InputStream input = getClass().getResourceAsStream(resource);
        file = File.createTempFile("tempfile", ".tmp");
        OutputStream out = new FileOutputStream(file);
        int read;
        byte[] bytes = new byte[1024];

        while ((read = input.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        out.close();
        file.deleteOnExit();
    } catch (IOException ex) {
        Exceptions.printStackTrace(ex);
    }
} else {
    //this will probably work in your IDE, but not from a JAR
    file = new File(res.getFile());
}

if (file != null && !file.exists()) {
    throw new RuntimeException("Error: File " + file + " not found!");
}

3
+1 এটি আমার পক্ষে কাজ করেছে। আপনি যে ফাইলগুলি binফোল্ডারে পড়তে চান তা নিশ্চিত করে রাখুন এবং `/com/myorg/filename.ext 'পাথ ব্যবহার করার আগে সংস্থানগুলিতে শ্রেণি লোডিংয়ের ডিরেক্টরিতে যান Make
রায়রেং

+1 এটি আমার পক্ষেও কাজ করে ... আমি বুঝতে পারি যে এই পদ্ধতির সাথে সম্পর্কিত কিছু সুরক্ষা ঝুঁকি থাকতে পারে, তাই আবেদন মালিকদের সে সম্পর্কে সচেতন হওয়া দরকার।
লুকাসা

আপনি কি এই বিবৃতিটি পরিষ্কার করতে পারেন "getResourceAsStream () দিয়ে কোনও সংস্থান লোড করা সর্বদা ভাল"? এটি কীভাবে সমস্যার সমাধান দিতে পারে?
লুকা এস 16

@LucaS। এটি কেবল চিত্রগুলির ক্ষেত্রে বোঝানো হয়েছিল, দুঃখিত এটি খুব পরিষ্কার ছিল না। পদ্ধতির প্ল্যাটফর্মটি স্বাধীন হওয়া উচিত, যদিও এটি কিছুটা হ্যাকি উপায়।
টম্বার্ট

@ লুকাসা আপনি যে ঝুঁকিগুলি উল্লেখ করেছেন তা পরিষ্কার করতে পারছেন?
জেডএক্স 9

25

এক লাইনের উত্তরটি হ'ল -

String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()

মূলত getResourceপদ্ধতিটি ইউআরএল দেয়। এই ইউআরএল থেকে আপনি কল করে পথটি বের করতে পারবেনtoExternalForm()

তথ্যসূত্র:

getResource () , ToExternForm ()


7
আমার পরিবেশ (ইন্টেলিজ) থেকে চলার সময় এটি একটি সাধারণ ফাইল ইউআরএল তৈরি করে যা সমস্ত ক্ষেত্রেই কাজ করে। যাইহোক, নিজেই জারটি থেকে চালানোর সময়, আমি জারের মতো একটি ইউআরআই পাই: ফাইল: /পাথ / টোজার / জার্নাম.জার! / ফাইল / ইন_জার.এমপি 4। জার দিয়ে শুরু হওয়া সমস্ত ইউআরআই ব্যবহার করতে পারে না। জাভাএফএক্স মিডিয়া পয়েন্টের ক্ষেত্রে।
নোহ তার্নুল্লো

1
আমার এই উত্তরটি সবচেয়ে ভাল লেগেছে। মঞ্জুর, বেশিরভাগ ক্ষেত্রে ইনপুট স্ট্রিমটি যখন কোনও জার ফাইলের মধ্যে থাকে তখন কেবল ইনপুটস্ট্রিমটি গ্রহণ করা ভাল but তবে যদি কোনও কারণে আপনার সত্যিকারের পথের প্রয়োজন হয় তবে এটি কাজ করে works তৃতীয় পক্ষের বস্তুটি দেওয়ার জন্য আমার পথের প্রয়োজন ছিল। সূতরাং ধন্যবাদ!
মারিও

1
উপরের সমাধানটি আইডিই করার সময় কাজ করে না, ইন্টেলিজিট file:/পথে যোগ করে, যা জারে কাজ করে তবে আইডিইতে নয়
তাইব হুসেন

আপনার প্রতিক্রিয়া এমন একটি সমস্যার সমাধান করেছে যে আমি এখন কমপক্ষে 2 দিন ধরে কাজ করার চেষ্টা করছি। Tyvm !!
জোনাথন

12

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

try {
    //Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
    //Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
    //Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
    PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.

    //Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
    try {
        PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
    } catch (Exception e) { }

    //Find the last / and cut it off at that location.
    PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
    //If it starts with /, cut it off.
    if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
    //If it starts with file:/, cut that off, too.
    if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
    PROGRAM_DIRECTORY = ""; //Current working directory instead.
}

8

যদি netclient.pকোনও জেআর ফাইলের অভ্যন্তরে থাকে তবে এর কোনও পাথ থাকবে না কারণ সেই ফাইলটি অন্য ফাইলে থাকা। সেক্ষেত্রে আপনার হতে পারে সর্বোত্তম পথই সত্য file:/path/to/jarfile/bot.jar!/config/netclient.p


যখন আমি চেষ্টা করি এবং এই ফর্ম্যাটটির একটি URL (... বোট.জার! / কনফিগারেশন / ...) ইউআরআইতে রূপান্তর করি তখন এটি বলছে যে পথটি শ্রেণিবদ্ধ নয়।
gEdringer

7

জার ফাইলের মধ্যে আপনার পথটি বুঝতে হবে।
কেবল এটি আপেক্ষিক উল্লেখ করুন। সুতরাং আপনার কাছে যদি কোনও ফাইল (মাইফাইল.টিএসটিএস্ট) থাকে, যা \src\main\resourcesডিরেক্টরিটির ( feld.txt ) ডিরেক্টরিতে অধীন foo.jar এ অবস্থিত । আপনি এটিকে উল্লেখ করুন:

src/main/resources/myfile.txt

আপনি যদি আপনার জারটি ব্যবহার করে ডাম্প করেন তবে আপনি jar -tvf myjar.jar জার ফাইলের মধ্যে আউটপুট এবং আপেক্ষিক পাথ দেখতে পাবেন এবং ফরওয়ার্ড স্ল্যাশগুলি ব্যবহার করবেন।


উইন্ডোতে আপনাকে অবশ্যই ফরোয়ার্ড স্ল্যাশ ব্যবহার করতে হবে। এটি বোঝায় যে আপনি ব্যবহার করতে পারবেন না File.separator
str

3

আমার ক্ষেত্রে, আমি পথের পরিবর্তে একটি URL অবজেক্ট ব্যবহার করেছি।

ফাইল

File file = new File("my_path");
URL url = file.toURI().toURL();

ক্লাসলোডার ব্যবহার করে ক্লাসপথে রিসোর্স

URL url = MyClass.class.getClassLoader().getResource("resource_name")

আমার যখন সামগ্রীটি পড়তে হবে তখন আমি নিম্নলিখিত কোডটি ব্যবহার করতে পারি:

InputStream stream = url.openStream();

এবং আপনি ইনপুট স্ট্রিম ব্যবহার করে সামগ্রীটি অ্যাক্সেস করতে পারেন।


3

জার রিসোর্স থেকে অসম্পূর্ণ অস্থায়ী ফাইল সামগ্রীর অনুলিপি এড়াতে এবং অনন্য টেম্প ফাইলের নাম রাখতে ব্যবহারকারী টম্বার্টের স্ট্রিম ফ্লাশ এবং কাছাকাছি থাকা একই কোড।

File file = null;
String resource = "/view/Trial_main.html" ;
URL res = getClass().getResource(resource);
if (res.toString().startsWith("jar:")) {
    try {
        InputStream input = getClass().getResourceAsStream(resource);
        file = File.createTempFile(new Date().getTime()+"", ".html");
        OutputStream out = new FileOutputStream(file);
        int read;
        byte[] bytes = new byte[1024];

        while ((read = input.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        out.flush();
        out.close();
        input.close();
        file.deleteOnExit();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
} else {
    //this will probably work in your IDE, but not from a JAR
    file = new File(res.getFile());
}
         

2

ফাইল সিস্টেমের কোনও ফাইলের জন্য একটি বিমূর্ততা এবং ফাইল সিস্টেমগুলি একটি জেআর এর সামগ্রী কী তা সম্পর্কে কিছুই জানে না।

একটি ইউআরআই দিয়ে চেষ্টা করুন, আমি মনে করি এমন একটি জার আছে: // প্রোটোকল যা আপনার পর্দাঘরের জন্য কার্যকর হতে পারে।


1

নিম্নলিখিত পথটি আমার পক্ষে কাজ করেছিল: classpath:/path/to/resource/in/jar


1
@Anatoly আপনি উপরের উপর আরো datails শেয়ার করুন গেল
Kasun Siyambalapitiya

1
private static final String FILE_LOCATION = "com/input/file/somefile.txt";

//Method Body


InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);

এ থেকে getSystemResourceAsStreamপাওয়া সেরা বিকল্প। ফাইল বা URL এর চেয়ে ইনপুটস্ট্রিম পেয়ে একটি জেআর ফাইলে কাজ করে এবং একা দাঁড়িয়ে থাকে।



0

যখন কোনও জার ফাইলে থাকে তবে সংস্থানটি প্যাকেজ হায়ারার্কিতে (ফাইল সিস্টেমের স্তরক্রম নয়) একেবারে অবস্থিত। সুতরাং আপনার যদি ক্লাস com.example.Wet "./default.conf" নামে একটি সংস্থান লোড হচ্ছে তবে সংস্থানটির নামটি "/com/example/default.conf" হিসাবে নির্দিষ্ট করা হবে।

তবে যদি এটি কোনও জারে থাকে তবে এটি কোনও ফাইল নয় ...


0

আপনার জারের আপনার রিসোর্স ফোল্ডার (জাভা / প্রধান / সংস্থানসমূহ) এর ভিতরে আপনার ফাইল যুক্ত করুন (আমরা ধরে নিই যে আপনি ইমপোর্টস.এক্সএমএল নামে একটি এক্সএমএল ফাইল যুক্ত করেছেন ) তারপরে আপনি ইনজেকশান করেন ResourceLoaderযদি আপনি ঝর্ণার মতো বসন্ত ব্যবহার করেন

@Autowired
private ResourceLoader resourceLoader;

ট্যুর ফাংশনের ভিতরে ফাইল লোড করার জন্য বেলো কোডটি লিখুন:

    Resource resource = resourceLoader.getResource("classpath:imports.xml");
    try{
        File file;
        file = resource.getFile();//will load the file
...
    }catch(IOException e){e.printStackTrace();}

0

হয়তো এই পদ্ধতিটি দ্রুত সমাধানের জন্য ব্যবহার করা যেতে পারে।

public class TestUtility
{ 
    public static File getInternalResource(String relativePath)
    {
        File resourceFile = null;
        URL location = TestUtility.class.getProtectionDomain().getCodeSource().getLocation();
        String codeLocation = location.toString();
        try{
            if (codeLocation.endsWith(".jar"){
                //Call from jar
                Path path = Paths.get(location.toURI()).resolve("../classes/" + relativePath).normalize();
                resourceFile = path.toFile();
            }else{
                //Call from IDE
                resourceFile = new File(TestUtility.class.getClassLoader().getResource(relativePath).getPath());
            }
        }catch(URISyntaxException ex){
            ex.printStackTrace();
        }
        return resourceFile;
    }
}

আপনি কিছু প্রসঙ্গ বাদ দিচ্ছেন? এটি আমাকে দেয়:java.lang.NullPointerException: Attempt to invoke virtual method 'java.security.CodeSource java.security.ProtectionDomain.getCodeSource()' on a null object reference
অ্যালেন লুসে

আমি উত্তরটি সম্পাদনা করে পুরো পদ্ধতিটি লিখেছিলাম যা আমি একটি সফ্টওয়্যারে ব্যবহার করেছি
gbii

0

কোড অনুসরণ করুন!

/ Src / প্রধান / সম্পদ / ফাইল

streamToFile(getClass().getClassLoader().getResourceAsStream("file"))

public static File streamToFile(InputStream in) {
    if (in == null) {
        return null;
    }

    try {
        File f = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
        f.deleteOnExit();

        FileOutputStream out = new FileOutputStream(f);
        byte[] buffer = new byte[1024];

        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }

        return f;
    } catch (IOException e) {
        LOGGER.error(e.getMessage(), e);
        return null;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.