আমি আমার জার ফাইলের অভ্যন্তর থেকে কীভাবে একটি সংস্থান "ফোল্ডার" পেতে পারি?


139

আমার প্রকল্পের মূলটিতে আমার একটি সংস্থান ফোল্ডার / প্যাকেজ রয়েছে, আমি একটি নির্দিষ্ট ফাইল লোড করতে চাই না। আমি যদি একটি নির্দিষ্ট ফাইল লোড করতে চাই, আমি Class.getResourceAsStream ব্যবহার করতাম এবং আমি ভাল থাকতাম !! আমি আসলে যা করতে চাই তা হ'ল রিসোর্স ফোল্ডারের মধ্যে একটি "ফোল্ডার" লোড করা, সেই ফোল্ডারের ভিতরে থাকা ফাইলগুলিতে লুপ করা এবং প্রতিটি ফাইলে একটি স্ট্রিম পাওয়া এবং কন্টেন্টে পড়া ... মনে করুন যে ফাইলের নাম রানটাইমের আগে নির্ধারিত নয় ... আমার কি করা উচিৎ? আপনার জার ফাইলটিতে কোনও ফোল্ডারের ভিতরে থাকা ফাইলগুলির একটি তালিকা পাওয়ার উপায় আছে? লক্ষ্য করুন যে সংস্থানগুলি সহ জার ফাইলটি সেই একই জার ফাইল যা থেকে কোডটি চালানো হচ্ছে ...

আগাম ধন্যবাদ...


1
এটি সহায়তা করবে: স্ট্যাকওভারফ্লো.com
জিগার জোশী


5
প্রথমটি একটি জার ফাইলটি বের করার বিষয়ে, যা আমি চেষ্টা করতে চাই এমন সর্বশেষ জিনিসটি, যদি-খারাপ-থেকে-খারাপ পরিস্থিতি আসে !! আমি যদি ফাইলগুলি আহরণ করতে চাই তবে আমি এগুলি কেবল ইনস্টলেশন সময়ে আমার ইনস্টলেশন ফোল্ডারে রেখে দেব! আমি এগুলি জারের ভিতর থেকে অ্যাক্সেস করতে চাই এবং আমার কারণ হ'ল যদি getResourceAsStream কোনও ফাইল অ্যাক্সেস করতে পারে তবে জাভাও সেই জারে ফোল্ডারগুলি অন্বেষণ করতে সক্ষম হওয়া উচিত, এটি বের করার প্রয়োজন ছাড়াই !! তবে ধন্যবাদ ...
মোস্তফা জেইনালি

উত্তর:


111

পরিশেষে, আমি সমাধানটি খুঁজে পেয়েছি:

final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());

if(jarFile.isFile()) {  // Run with JAR file
    final JarFile jar = new JarFile(jarFile);
    final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
    while(entries.hasMoreElements()) {
        final String name = entries.nextElement().getName();
        if (name.startsWith(path + "/")) { //filter according to the path
            System.out.println(name);
        }
    }
    jar.close();
} else { // Run with IDE
    final URL url = Launcher.class.getResource("/" + path);
    if (url != null) {
        try {
            final File apps = new File(url.toURI());
            for (File app : apps.listFiles()) {
                System.out.println(app);
            }
        } catch (URISyntaxException ex) {
            // never happens
        }
    }
}

দ্বিতীয় ব্লকটি তখনই কাজ করে যখন আপনি আইডিইতে অ্যাপ্লিকেশনটি চালান (জার ফাইল সহ নয়), আপনি যদি এটি পছন্দ না করেন তবে আপনি এটি সরাতে পারেন।


সঠিক উত্তর আপডেট করেছেন। যদিও আমি এটি করতে চাই না, বিশেষত 34000+ উত্স ফাইল সহ একটি কোডে ... তবে এটি কেবলমাত্র সমাধান বলে মনে হয়। ধন্যবাদ.
মোস্তফা জিনালি

4
এফওয়াইআই, ওয়েবস্টার্ট থেকে চালু করা থাকলে এটি কাজ করে না কারণ গেটপ্যাথ সার্ভারের ডোমেনের সাথে সম্পর্কিত কিছু দেয়।
amos

1
ভাববেন না যে পথটি জারে থাকলে এটি কাজ করছে, টুআরআই রূপান্তরকরণে এই ত্রুটিটি দেবে: java.lang.IllegalArgumentException: ইউআরআই শ্রেণিবদ্ধ নয়
ট্রিপব্লাইড

4
কেবলমাত্র অন্য বয়াম মধ্যে নির্ভরতা থেকে নির্যাস সম্পদ কাজ একক বয়াম ফাইল জন্য কাজ করে, না
tribbloid

2
এটি কোনও নিরাপদ সমাধান নয়, কারণ: ১. এটি ধরে ধরেছে যে .jar ফাইলটি একই সিস্টেমে একটি স্থানীয় ফাইল; ২. URL.getPath () কোনও বৈধ ফাইলের নাম দেয় না, এটি কেবলমাত্র URL- এর অংশ অংশটি দেয়, সমস্ত শতাংশ-পলায়ন অক্ষত রেখে; 3. ProtectionDomain.getCodeSource () নাল আসতে পারেন
ভিজিআর

14

নিম্নলিখিত চেষ্টা করুন। আপনার শ্রেণীর পথটি যদি com.abc.package.MyClass এবং আপনার পুনরায় ফাইলগুলি src / com / abc / প্যাকেজ / সংস্থান / এর মধ্যে থাকে তবে উত্সের
পথটি তৈরি করুন "<PathRelativeToThisClassFile>/<ResourceDirectory>":

URL url = MyClass.class.getResource("resources/");
if (url == null) {
     // error - missing folder
} else {
    File dir = new File(url.toURI());
    for (File nextFile : dir.listFiles()) {
        // Do something with nextFile
    }
}

আপনি ব্যবহার করতে পারেন

URL url = MyClass.class.getResource("/com/abc/package/resources/");

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

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

1
স্রেফ কোডটি একটি পাত্রে চালিয়ে ত্রুটিটি পেয়ে গেল ... উফ! ভি দুঃখিত, আমার খারাপ। "ফাইল: ...! / Dir1 / dir2 ..." দিয়ে জার ইউআরএল পাথ পরিচালনা করতে হবে। দুই সংশোধন করা হয়েছে: stackoverflow.com/questions/1429172/... । বা স্ট্রিং jarPath = dirURL.getPath () সাবস্ট্রিং (। "!" 5, dirURL.getPath () indexOf মধ্যে ()); জারফিল জার = নতুন জারফিল (ইউআরএলডিকোডার.ডেকোড (জারপথ, "ইউটিএফ -8")); গণনা <জারেন্ট্রি> এন্ট্রি = জার.এন্ট্রি (); যখন (এন্ট্রি.হাসমোরি এলিমেন্টস ()) {// কিছু করুন}
গ্লেন বেস্ট

3
জাভাডোক থেকে স্পষ্টতই যে পদ্ধতিটি সব পরিস্থিতিতে কোনও ফাইল ফেরত দেওয়ার গ্যারান্টিযুক্ত নয়। কিন্তু, আপনি যদি সত্যই কিউটি পড়েন তবে ওপি নির্মাণের মাধ্যমে ফাইল এবং ফোল্ডারগুলির সাথে কাজ করার 100% গ্যারান্টিযুক্ত। প্রশ্নটি ডিরেক্টরি এবং ফাইলগুলিতে অ্যাক্সেস পেতে বলছে - এটি আরও নির্দিষ্ট যা এপিআইয়ের সাধারণ বিমূর্ততা। ফাইলটি রূপান্তর করা প্রয়োজন মেটাতে উপযুক্ত এবং সঠিক। এই জাতীয় দৃ contrary় বিপরীত মন্তব্য পোস্ট করার আগে দয়া করে Q টি সঠিকভাবে পড়ুন। চিয়ার্স।
গ্লেন সেরা

7
ওপি ফাইল এবং ডিরেক্টরি নিয়ে কাজ করছে না। তিনি একটি জেআর ফাইলটিতে সংস্থান নিয়ে কাজ করছেন। একটি JAR ফাইলের সংস্থানগুলি ফাইল বা ডিরেক্টরি নয় এবং Fileশ্রেণীর সাথে তালিকাভুক্ত করা যায় না । এই কোডটি কোনও জেআর ফাইলের অভ্যন্তরে সংস্থান দিয়ে কাজ করে না। সময়কাল।
লার্নের মার্কুইস

7

আমি জানি এটি বহু বছর আগের। তবে কেবল অন্য ব্যক্তির জন্যই এই বিষয়টি জুড়ে। আপনি যা করতে পারেন তা হ'ল getResourceAsStream()ডিরেক্টরি পথ সহ পদ্ধতিটি ব্যবহার করা এবং ইনপুট স্ট্রিমের সেই দির থেকে সমস্ত ফাইলের নাম থাকবে। এর পরে আপনি প্রতিটি ফাইলের নামের সাথে ডায়ার পাথকে সংহত করতে পারেন এবং প্রতিটি ফাইলের জন্য একটি লুপে getResourceAsStream কল করতে পারেন।


7
আপনি যদি ঝাঁকুনির বিষয়ে পরিকল্পনা না করেন তবে এটি ভাল কাজ করে।
Tustin2121

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

6

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

আমি java.nio.file.DirectoryStreamস্থানীয় ফাইল সিস্টেম এবং জার উভয়ই ডিরেক্টরি সামগ্রীতে পুনরাবৃত্তি করতে সবচেয়ে ভাল কাজ খুঁজে পেয়েছি ।

String fooFolder = "/foo/folder";
....

ClassLoader classLoader = foofClass.class.getClassLoader();
try {
    uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
    throw new FooException(e.getMessage());
} catch (NullPointerException e){
    throw new FooException(e.getMessage());
}

if(uri == null){
    throw new FooException("something is wrong directory or files missing");
}

/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
    /** jar case */
    try{
        URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
        //jar.toString() begins with file:
        //i want to trim it out...
        Path jarFile = Paths.get(jar.toString().substring("file:".length()));
        FileSystem fs = FileSystems.newFileSystem(jarFile, null);
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
        for(Path p: directoryStream){
            InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
        performFooOverInputStream(is);
        /** your logic here **/
            }
    }catch(IOException e) {
        throw new FooException(e.getMessage());     
    }
}
else{
    /** IDE case */
    Path path = Paths.get(uri);
    try {
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
        for(Path p : directoryStream){
            InputStream is = new FileInputStream(p.toFile());
            performFooOverInputStream(is);
        }
    } catch (IOException _e) {
        throw new FooException(_e.getMessage());
    }
}

এটি আমার পক্ষে ভাল কাজ করেছে। কেবলমাত্র আমি 'পথ jarFile = Paths.get (jar.toString ()। স্ট্রিং ("ফাইল:"। দৈর্ঘ্য ())) স্যুইচ করেছি;' 'পাথ জারফিল = পাথস.জেট (jar.toURI ()) সহ; এটি উইন্ডোতে কাজ করার জন্য। ফাইলসিসটেম অবজেক্টের জন্য রিসোর্স স্টেটমেন্ট সহ চেষ্টা করেও ব্যবহার করা হয়েছে।
জারলে জ্যাকবসেন

এটি আমার পক্ষে কাজ করেছিল! আমি ডকারে ড্রপউইজার্ড অ্যাপ্লিকেশন চালাচ্ছিলাম।
nIKUNJ

4

নীচের কোডটি একটি জারের ভিতরে রয়েছে কিনা তা নির্বিশেষে পাথ হিসাবে ওয়ান্টেড "ফোল্ডার "টিকে ফেরত দেয়।

  private Path getFolderPath() throws URISyntaxException, IOException {
    URI uri = getClass().getClassLoader().getResource("folder").toURI();
    if ("jar".equals(uri.getScheme())) {
      FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
      return fileSystem.getPath("path/to/folder/inside/jar");
    } else {
      return Paths.get(uri);
    }
  }

জাভা 7+ প্রয়োজন।


নিস! যদিও আপনাকে যুক্ত করতে হবে, ফাইলসিস্টেমটি ক্লোজেবল, যার অর্থ এটি আপনাকে কোনও সময় ফ্রি সিস্টেমের সংস্থানগুলিতে বন্ধ করতে হবে। অবশ্যই, এরপরেই ফিরে আসা পথটি অবৈধ হয়ে যাবে।
কিরিল গামাজকভ

নোট করুন যে কোনও জার ফাইলের ক্ষেত্রে ফাইল সিস্টেম তৈরি করার সময় সংস্থানটির নাম (এখানে প্যাকেজ + folder) উপেক্ষা করা হবে বলে মনে হয়। সুতরাং getPathফিরে না folder/path/to/..., কিন্তু শুধুমাত্র path/to/...
Marcono1234

1

আর একটি সমাধান, আপনি এটি ব্যবহার করে এটি করতে পারেন ResourceLoader:

import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;

@Autowire
private ResourceLoader resourceLoader;

...

Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
    load(fi.next())
}

0

সরল ... ওএসজি ব্যবহার করুন। ওএসজিআইতে আপনি ফাইন্ডএন্ট্রি এবং ফাইন্ডপ্যাথগুলির সাহায্যে আপনার বান্ডিলের এন্ট্রিগুলিতে পুনরাবৃত্তি করতে পারেন।


10
এতে যদি ওএসজিআই জড়িত থাকে তবে আমি এটিকে 'সিম্পল' বলি না। তবে যদি আপনি ইতিমধ্যে ওএসজিআই ব্যবহার করছেন ... হ্যাঁ অবশ্যই। তবে কেবলমাত্র এই নির্দিষ্ট সমস্যাটি সমাধান করার জন্য ওএসজিআইতে যাওয়ার পরামর্শ দেওয়া কিছুটা বেশি মনে হচ্ছে।
ক্রিস

ওএসজিআই আরও অনেক সমস্যা সমাধান করে এবং আজকাল এটি শুরু করা খুব সহজ। ওএসজিআই এনআরউউট টিউটোরিয়ালগুলি দেখুন
পিটার ক্রিয়েন্স

আপনার যদি ইতিমধ্যে এটির প্রয়োজন না হয় তবে আমি ওএসজি থেকে দূরে থাকব। ওভার ডিজাইন করা ব্লাটওয়্যার যা 90 এর দশকের আইএমওর স্থাপনার সমস্যাগুলি সমাধান করে।
ব্যবহারকারী 2337270

-1

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

URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);

URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);

URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

1
হাই, উত্তরের জন্য ধন্যবাদ, তবে, আপনি দেখুন, কোডটি লেখার সময় আপনাকে সেই ফোল্ডারের ভিতরে প্রতিটি ফাইলের নাম জানা দরকার; এবং আপনার প্রত্যেকটির নাম স্পষ্টভাবে উল্লেখ করতে হবে। আমি যা সন্ধান করছিলাম সেটি হ'ল ফোল্ডারের অভ্যন্তরে থাকা ফাইলগুলিতে পুনরাবৃত্তি হওয়া এবং রানটাইমের সময় তাদের নামগুলি পাওয়ার জন্য, তাই আমি কোডটি পরিবর্তন না করেই ফোল্ডারে সংস্থান যুক্ত করতে পারলাম, কোডটি না জেনেও সেগুলি প্রক্রিয়া করবে। যদিও আপনার সময় জন্য ধন্যবাদ। : 3
মোস্তফা জেইনালি

-1

অন্যান্য উত্তরগুলি নির্দেশ করে, একবার সংস্থানগুলি একটি জার ফাইলের মধ্যে পরে জিনিসগুলি সত্যই খারাপ হয়। আমাদের ক্ষেত্রে, এই সমাধান:

https://stackoverflow.com/a/13227570/516188

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

এইভাবে আমার অ্যাপে আমার সহজ কোড রয়েছে (কোনও কৌশল নয়) এবং আমি নিশ্চিত যে পরীক্ষার জন্য আমি তালিকায় নতুন এন্ট্রি যুক্ত করতে ভুলিনি।


-25

এই লিঙ্কটি আপনাকে জানায় কীভাবে।

যাদুটি হ'ল getResourceAsStream () পদ্ধতি:

InputStream is = 
this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml")

20
না বাবা !! আমি একটি ফাইল চাই না !! আমি একটি সম্পূর্ণ ফোল্ডার চাই, যার সাব ফাইলগুলি প্রাক রানটাইম নির্ধারিত হয় !!!
মোস্তফা জেইনালি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.