JAR ফাইলের মধ্যে ফাইলগুলি কীভাবে তালিকাভুক্ত করবেন?


114

আমার কাছে এই কোডটি রয়েছে যা একটি ডিরেক্টরি থেকে সমস্ত ফাইল পড়ে।

    File textFolder = new File("text_directory");

    File [] texFiles = textFolder.listFiles( new FileFilter() {
           public boolean accept( File file ) {
               return file.getName().endsWith(".txt");
           }
    });

এটি দুর্দান্ত কাজ করে। ডিরেক্টরিটি "টেক্সট_ডাইরেক্টরি" থেকে ".txt" দিয়ে শেষ হওয়া সমস্ত ফাইল এটি অ্যারে পূরণ করে।

আমি কীভাবে কোনও JAR ফাইলের মধ্যে একটি অনুরূপ ফ্যাশনে ডিরেক্টরিগুলির বিষয়বস্তু পড়তে পারি ?

সুতরাং আমি যা করতে চাই তা হ'ল আমার জেআর ফাইলের ভিতরে থাকা সমস্ত চিত্রের তালিকা করা, যাতে আমি এগুলি লোড করতে পারি:

ImageIO.read(this.getClass().getResource("CompanyLogo.png"));

(এটি একটি কাজ করে কারণ "CompanyLogo" "হার্ডকোডযুক্ত" তবে জেআর ফাইলের অভ্যন্তরে চিত্রগুলির সংখ্যা 10 থেকে 200 ভেরিয়েবলের দৈর্ঘ্য হতে পারে))

সম্পাদনা

সুতরাং আমি অনুমান করি যে আমার মূল সমস্যাটি হ'ল: আমার প্রধান শ্রেণি যেখানে থাকে সেই জেআর ফাইলটির নাম কীভাবে জানব ?

মঞ্জরি আমি ব্যবহার করে এটি পড়তে পারে java.util.Zip

আমার কাঠামোটি এরকম:

তারা হ'ল:

my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest 

এখনই উদাহরণস্বরূপ "চিত্রগুলি / চিত্র01.png" ব্যবহার করে লোড করতে সক্ষম হচ্ছি:

    ImageIO.read(this.getClass().getResource("images/image01.png));

তবে কেবলমাত্র আমি ফাইলের নাম জানি কারণ, বাকিগুলির জন্য আমাকে এগুলি গতিশীলভাবে লোড করতে হবে।


কেবল একটি চিন্তা - কেন একটি পৃথক ফাইলে জিপ / জার চিত্রগুলি না করে অন্য শ্রেণিতে আপনার শ্রেণি থেকে এতে থাকা এন্ট্রিগুলি পড়ছেন?
ভিনিতে রেনল্ডস

3
কারণ বিতরণ / ইনস্টলেশনের জন্য এটি একটি "অতিরিক্ত" পদক্ষেপ প্রয়োজন। :( আপনি জানেন, শেষ ব্যবহারকারীগণ
অস্কাররাইজ

আপনি জার তৈরি করেছেন তা প্রদত্ত, আপনি কোনও কৌশল চেষ্টা করার পরিবর্তে এর মধ্যে ফাইলগুলির তালিকাও অন্তর্ভুক্ত করতে পারেন।
টম হাটিন -

ঠিক আছে, আমার ভুল হতে পারে তবে অন্যান্য জারগুলির মধ্যে জারগুলি এম্বেড করা যেতে পারে। ওয়ান-জার (টিএম) প্যাকেজিং সলিউশন আইবিএম / ডেভেলপ ওয়ার্কস / জাভা / লাইব্রেরি / জেজনার এই ভিত্তিতে কাজ করে। বাদে আপনার ক্ষেত্রে আপনার জন্য দক্ষতার লোড ক্লাসের প্রয়োজন হবে না।
ভিনিতে রেনল্ডস

উত্তর:


91
CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
  URL jar = src.getLocation();
  ZipInputStream zip = new ZipInputStream(jar.openStream());
  while(true) {
    ZipEntry e = zip.getNextEntry();
    if (e == null)
      break;
    String name = e.getName();
    if (name.startsWith("path/to/your/dir/")) {
      /* Do something with this entry. */
      ...
    }
  }
} 
else {
  /* Fail... */
}

নোট করুন যে জাভা 7-এ, আপনি FileSystemজার (জিপ) ফাইলটি থেকে একটি তৈরি করতে পারেন এবং তারপরে অনুসন্ধানের জন্য এনআইওর ডিরেক্টরি হাঁটা এবং ফিল্টারিং পদ্ধতি ব্যবহার করতে পারেন। এটি JARs এবং "বিস্ফোরিত" ডিরেক্টরি পরিচালনা করে এমন কোড লিখতে সহজ করবে।


আরে ধন্যবাদ ... এখন কয়েক ঘন্টা ধরে এটি করার উপায় খুঁজছেন !!
নিউটোপিয়ান

9
হ্যাঁ এই কোডটি কাজ করে যদি আমরা এই জার ফাইলের মধ্যে সমস্ত এন্ট্রি তালিকাবদ্ধ করতে চাই। তবে আমি যদি কেবল জারের অভ্যন্তরে একটি উপ-ডিরেক্টরি তালিকাবদ্ধ করতে চাই, উদাহরণস্বরূপ, উদাহরণ .jar / dir1 / dir2 / , আমি কীভাবে সরাসরি এই উপ-ডিরেক্টরিতে সমস্ত ফাইল তালিকাভুক্ত করতে পারি? অথবা আমার এই জার ফাইলটি আনজিপ করা দরকার? আমি আপনার সাহায্যের খুব প্রশংসা করি!
এনসোম হজদার

উল্লেখ করা জাভা 7 পদ্ধতির @ অ্যাকেরন 55 এর উত্তরে তালিকাভুক্ত করা হয়েছে ।
ভাদজিম

@ ভ্যাডজিম আপনি কি নিশ্চিতই জাভা for এর জন্য অ্যাকেরন 55 এর উত্তর? আমি জাভা 7 তে ফাইলসওয়াক () বা জাভা.ইটিল.স্ট্রিম খুঁজে পাইনি, তবে জাভা 8 তে: ডকস.ওরকল
ব্রুস সূর্যের

ব্রুসসন, জাভা in-এ আপনি এর পরিবর্তে ফাইলস.ওয়ালকফাইলেট্রি (...) ব্যবহার করতে পারেন ।
ভাদজিম

79

কোড যা আইডিই এবং .jar ফাইল উভয়ের জন্য কাজ করে:

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;

public class ResourceWalker {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URI uri = ResourceWalker.class.getResource("/resources").toURI();
        Path myPath;
        if (uri.getScheme().equals("jar")) {
            FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
            myPath = fileSystem.getPath("/resources");
        } else {
            myPath = Paths.get(uri);
        }
        Stream<Path> walk = Files.walk(myPath, 1);
        for (Iterator<Path> it = walk.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
    }
}

5
FileSystems.newFileSystem()এটি গ্রহণ করে Map<String, ?>, সুতরাং আপনার উল্লেখ করতে হবে Collections.emptyMap()যে এটি উপযুক্ত টাইপ করা একটি ফেরত দরকার। এই কাজ করে: Collections.<String, Object>emptyMap()
জিরো 3

6
ফ্যান্টাস্টিক !!! তবে ইউআরআই uri = MyClass.class.getResource ("/ রিসোর্স")। টুরি (); MyClass.class.getClassLoader () থাকতে হবে। getResource ("/ রিসোর্স")। টুরি (); অর্থাত্, getClassLoader ()। অন্যথায় এটি আমার পক্ষে কাজ করে না।
ইএমএম

8
বন্ধ করতে ভুলবেন না fileSystem!
gmjonker

3
এটি 1.8 এর প্রথম উত্তর হওয়া উচিত ( walkপদ্ধতিটি Filesকেবলমাত্র 1.8 এ উপলব্ধ)। কেবলমাত্র সমস্যাটি হ'ল সংস্থানসমূহের ডিরেক্টরিটি Files.walk(myPath, 1)কেবল ফাইলগুলিতেই উপস্থিত হয় না। আমার ধারণা প্রথম উপাদানটি সহজেই উপেক্ষা করা যেতে পারে
টোটো_টিকো

4
myPath = fileSystem.getPath("/resources");আমার জন্য কাজ করে না; এটি কিছুই খুঁজে পায় না। এটি আমার ক্ষেত্রে "চিত্র" হওয়া উচিত এবং "চিত্রগুলি" -ডাইরেক্টরিটি অবশ্যই আমার জারে অন্তর্ভুক্ত রয়েছে!
phip1611

21

এরিকসনের উত্তর পুরোপুরি কার্যকর হয়েছিল:

এখানে ওয়ার্কিং কোড।

CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
List<String> list = new ArrayList<String>();

if( src != null ) {
    URL jar = src.getLocation();
    ZipInputStream zip = new ZipInputStream( jar.openStream());
    ZipEntry ze = null;

    while( ( ze = zip.getNextEntry() ) != null ) {
        String entryName = ze.getName();
        if( entryName.startsWith("images") &&  entryName.endsWith(".png") ) {
            list.add( entryName  );
        }
    }

 }
 webimages = list.toArray( new String[ list.size() ] );

এবং আমি এ থেকে আমার লোড পদ্ধতিটি পরিবর্তন করেছি:

File[] webimages = ... 
BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex].getName() ));

এটি:

String  [] webimages = ...

BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex]));

9

আমি অ্যাকেরন 55 এর উত্তরটি প্রসারিত করতে চাই , যেহেতু এটি বেশ কয়েকটি কারণে খুব নিরাপদ সমাধান reasons

  1. এটি FileSystemবস্তুটি বন্ধ করে না ।
  2. এটি FileSystemইতিমধ্যে উপস্থিত আছে কিনা তা পরীক্ষা করে না ।
  3. এটি থ্রেড-নিরাপদ নয়।

এটি কিছুটা নিরাপদ সমাধান:

private static ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();

public void walk(String path) throws Exception {

    URI uri = getClass().getResource(path).toURI();
    if ("jar".equals(uri.getScheme()) {
        safeWalkJar(path, uri);
    } else {
        Files.walk(Paths.get(path));
    }
}

private void safeWalkJar(String path, URI uri) throws Exception {

    synchronized (getLock(uri)) {    
        // this'll close the FileSystem object at the end
        try (FileSystem fs = getFileSystem(uri)) {
            Files.walk(fs.getPath(path));
        }
    }
}

private Object getLock(URI uri) {

    String fileName = parseFileName(uri);  
    locks.computeIfAbsent(fileName, s -> new Object());
    return locks.get(fileName);
}

private String parseFileName(URI uri) {

    String schemeSpecificPart = uri.getSchemeSpecificPart();
    return schemeSpecificPart.substring(0, schemeSpecificPart.indexOf("!"));
}

private FileSystem getFileSystem(URI uri) throws IOException {

    try {
        return FileSystems.getFileSystem(uri);
    } catch (FileSystemNotFoundException e) {
        return FileSystems.newFileSystem(uri, Collections.<String, String>emptyMap());
    }
}   

ফাইলের নামের সাথে সিঙ্ক্রোনাইজ করার কোনও আসল প্রয়োজন নেই; প্রতিবারে একই পদে একজন সহজেই সিঙ্ক্রোনাইজ করতে পারে (বা পদ্ধতিটি তৈরি করুন synchronized), এটি নিখুঁতভাবে একটি অপ্টিমাইজেশন।

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

এই নির্দিষ্ট জাভা এনআইও ইন্টারফেসটি এক ধরণের ভয়ঙ্কর, যেহেতু এটি একটি গ্লোবাল / সিঙ্গলটন নন থ্রেড-নিরাপদ সংস্থান প্রবর্তন করে এবং এর ডকুমেন্টেশনটি অত্যন্ত অস্পষ্ট (সরবরাহকারীর নির্দিষ্ট প্রয়োগের কারণে অনেকগুলি অজানা)। অন্যান্য FileSystemসরবরাহকারীদের জন্য ফলাফল পৃথক হতে পারে (জেআর নয়)। সম্ভবত এটির পক্ষে থাকার পক্ষে ভাল কারণ রয়েছে; আমি জানি না, আমি বাস্তবায়নগুলি নিয়ে গবেষণা করিনি।


1
এফএসের মতো বহিরাগত সংস্থাগুলির সুসংগতকরণের কোনও ভিএম-এর মধ্যে খুব বেশি ধারণা নেই। আপনার ভিএম এর বাইরে এটি অ্যাক্সেস করার মতো অন্যান্য অ্যাপ্লিকেশন থাকতে পারে। এমনকি আপনার নিজের অ্যাপ্লিকেশনের অভ্যন্তরে, ফাইলের উপর ভিত্তি করে আপনার লকিং সহজেই বাইপাস করা যায়। এই জিনিসগুলির সাথে ফাইল লক করার মতো ওএস সিঙ্ক্রোনাইজেশন প্রক্রিয়ার উপর নির্ভর করা ভাল।
এস্পিনোসা

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

8

সুতরাং আমি অনুমান করি যে আমার মূল সমস্যাটি হ'ল, আমার প্রধান শ্রেণি যেখানে বাস করে তার জার নামটি কীভাবে জানব।

ধরে নিই যে আপনার প্রকল্পটি একটি জারে প্যাক করা আছে (অগত্যা সত্য নয়!), আপনি প্রদত্ত শ্রেণীর অন্তর্ভুক্ত জারটি পেতে ClassLoader.getResource () বা ফাইন্ড রিসোর্স () ক্লাসের নাম (অনুসরণ করে) ব্যবহার করতে পারেন by আপনাকে ফিরে আসা URL (যেটি শক্ত নয়) থেকে জারের নামটি পার্স করতে হবে, যা আমি পাঠকের জন্য অনুশীলন হিসাবে ছেড়ে দেব :-)

ক্লাসটি কোনও জারের অংশ নয় এমন ক্ষেত্রে পরীক্ষা করার জন্য নিশ্চিত হন।


1
হুঁ - আকর্ষণীয় যে এটি মন্তব্য ছাড়াই মোড করা হত ... আমরা উপরের কৌশলটি সমস্ত সময় ব্যবহার করি এবং এটি ঠিক কাজ করে works
কেভিন ডে

একটি পুরানো ইস্যু, তবে আমার কাছে এটি দুর্দান্ত হ্যাকের মতো মনে হচ্ছে। শুন্যতে :) ফিরে সম্মত
Tuukka Mustonen

উত্সাহিত, কারণ এই শ্রেণীর কাছে যখন কেবল শ্রেণীর কাছে না থাকে তবে এই ক্ষেত্রে কেবলমাত্র এখানে তালিকাভুক্ত সমাধান CodeSource
মনিকা 2331977

7

আমি জাভা 7 এ অ্যাকেরন 55 এর উত্তরটি পোর্ট করেছি এবং FileSystemঅবজেক্টটি বন্ধ করে দিয়েছি । এই কোডটি আইডিই-তে, জার ফাইলগুলিতে এবং টমকেট 7-এর যুদ্ধের অভ্যন্তরে একটি পাত্রে কাজ করে; কিন্তু মনে রাখবেন যে নেই না JBoss 7 যুদ্ধের ভিতরে বয়াম কাজ (এটা দেয় FileSystemNotFoundException: Provider "vfs" not installed, এছাড়াও দেখুন এই পোস্টে )। তদতিরিক্ত, মূল কোডের মতো এটিও থ্রেড নিরাপদ নয়, যেমনটি এরর দ্বারা প্রস্তাবিত । এই কারণে আমি এই সমাধানটি ত্যাগ করেছি; তবে আপনি যদি এই বিষয়গুলি গ্রহণ করতে পারেন তবে আমার তৈরি কোডটি এখানে:

import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;

public class ResourceWalker {

    public static void main(String[] args) throws URISyntaxException, IOException {
        URI uri = ResourceWalker.class.getResource("/resources").toURI();
        System.out.println("Starting from: " + uri);
        try (FileSystem fileSystem = (uri.getScheme().equals("jar") ? FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap()) : null)) {
            Path myPath = Paths.get(uri);
            Files.walkFileTree(myPath, new SimpleFileVisitor<Path>() { 
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    System.out.println(file);
                    return FileVisitResult.CONTINUE;
                }
            });
        }
    }
}

5

"একটি প্যাকেজের অধীনে সমস্ত JUnits চালান" এর জন্য আমি একটি পদ্ধতি লিখেছি। আপনার এটি আপনার প্রয়োজনের সাথে খাপ খাইয়ে নিতে সক্ষম হওয়া উচিত।

private static void findClassesInJar(List<String> classFiles, String path) throws IOException {
    final String[] parts = path.split("\\Q.jar\\\\E");
    if (parts.length == 2) {
        String jarFilename = parts[0] + ".jar";
        String relativePath = parts[1].replace(File.separatorChar, '/');
        JarFile jarFile = new JarFile(jarFilename);
        final Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            final JarEntry entry = entries.nextElement();
            final String entryName = entry.getName();
            if (entryName.startsWith(relativePath)) {
                classFiles.add(entryName.replace('/', File.separatorChar));
            }
        }
    }
}

সম্পাদনা: আহ, সেক্ষেত্রে আপনি এই স্নিপেটটিও চাইবেন (একই ব্যবহারের ক্ষেত্রে :))

private static File findClassesDir(Class<?> clazz) {
    try {
        String path = clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
        final String codeSourcePath = URLDecoder.decode(path, "UTF-8");
        final String thisClassPath = new File(codeSourcePath, clazz.getPackage().getName().repalce('.', File.separatorChar));
    } catch (UnsupportedEncodingException e) {
        throw new AssertionError("impossible", e);
    }
}

1
আমার ধারণা বড় সমস্যাটি হ'ল জারের ফাইলের নামটি প্রথম স্থানে জানা। এটিই জার যেখানে মূল-শ্রেণি: বাস করে।
অস্কারলাইজ

5

রিফ্লেক্স লাইব্রেরি ব্যবহার করে উদাহরণস্বরূপ রিসর্ট নাম প্যাটার্ন দ্বারা ক্লাসপাথটি স্ক্যান করতে পুনরায় সংস্থানগুলি সংগ্রহ করার জন্য কয়েকটি পেয়ারা পারফরম্যান্সের সাহায্যে যুক্ত করা যেতে পারে:

Reflections reflections = new Reflections("com.example.package", new ResourcesScanner());
Set<String> paths = reflections.getResources(Pattern.compile(".*\\.template$"));

Map<String, String> templates = new LinkedHashMap<>();
for (String path : paths) {
    log.info("Found " + path);
    String templateName = Files.getNameWithoutExtension(path);
    URL resource = getClass().getClassLoader().getResource(path);
    String text = Resources.toString(resource, StandardCharsets.UTF_8);
    templates.put(templateName, text);
}

এটি উভয় জার এবং বিস্ফোরিত শ্রেণীর সাথে কাজ করে।


সাবধান থাকুন যে প্রতিচ্ছবিগুলি এখনও জাভা 9 এবং তারপরে সমর্থন করে না: github.com/ronmamo/reflections/issues/186 । সেখানে প্রতিযোগী পাঠাগারগুলির লিঙ্ক রয়েছে are
ভাদজিম

3

একটি জার ফাইল কেবল কাঠামোগত ম্যানিফেস্টের সাথে একটি জিপ ফাইল। আপনি জারার জিপ জিপ সরঞ্জামগুলির সাহায্যে জার ফাইলটি খুলতে পারেন এবং সেভাবে ফাইলের সামগ্রীগুলি স্ক্যান করতে পারেন, প্রবাহিত স্ট্রিম ইত্যাদি Then

সম্পাদনা / স্পষ্টির পরে

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

InputStream inputStream = SomeClass.class.getClassLoader().getResourceAsStream("image.jpg");
JPEGImageReaderSpi imageReaderSpi = new JPEGImageReaderSpi();
ImageReader ir = imageReaderSpi.createReaderInstance();
ImageInputStream iis = new MemoryCacheImageInputStream(inputStream);
ir.setInput(iis);
....
ir.read(0); //will hand us a buffered image

এই জারে মূল প্রোগ্রাম এবং সংস্থানগুলি রয়েছে। আমি কীভাবে সেল্ফ জারটি উল্লেখ করব? জার ফাইলের মধ্যে থেকে?
অস্কাররাজ

JAR ফাইলটি উল্লেখ করতে, স্ট্রিং হিসাবে কেবল "blah.JAR" ব্যবহার করুন। আপনি new File("blah.JAR")উদাহরণস্বরূপ, জারকে উপস্থাপন করে এমন একটি ফাইল অবজেক্ট তৈরি করতে ব্যবহার করতে পারেন । আপনার জারের নাম দিয়ে কেবল "বেলা.জেআর" প্রতিস্থাপন করুন।
থমাস

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

2
আচ্ছা হ্যাঁ, আমার কাছে ইতিমধ্যে তা ছিল, যখন সমস্যাটির দরকার হয় তখন যখন আমার মতো কিছু দরকার হয়: "... getResourceAsStream (" *। Jpg "); ..." এটি গতিশীলভাবে থাকা ফাইলগুলির তালিকাবদ্ধ করুন।
অস্কাররাজ

3

একটি আসল জেআর ফাইল দেওয়া, আপনি ব্যবহার করে বিষয়বস্তু তালিকা করতে পারেন JarFile.entries()। আপনার জেআর ফাইলের অবস্থানটি জানা দরকার - তবে আপনি কেবল ক্লাসলোডারকে যা পেতে পারে তার সমস্ত কিছু তালিকা করতে বলতে পারেন না।

আপনার কাছ থেকে ফিরে আসা ইউআরএলের উপর ভিত্তি করে জেআর ফাইলের অবস্থানের বিষয়ে কাজ করতে সক্ষম হওয়া উচিত ThisClassName.class.getResource("ThisClassName.class"), তবে এটি খুব সামান্য বিস্মৃত হতে পারে।


আপনার উত্তর পড়তে গিয়ে আরও একটি প্রশ্ন ওঠে। কলটি কী দেবে: this.getClass ()। GetResource ("/ my_directory"); এটি এমন একটি ইউআরএল ফিরিয়ে দেবে যা পরিবর্তিত হতে পারে .... ডিরেক্টরি হিসাবে ব্যবহৃত হতে পারে? নাহ ... আমাকে চেষ্টা করে দেখি।
অস্কাররাইজ

আপনি জেআর এর অবস্থানটি সর্বদা জানেন it's এটিতে "।" যতক্ষণ না জেআর নামটি কিছু হিসাবে পরিচিত, আপনি কোথাও স্ট্রিং ধ্রুবক ব্যবহার করতে পারেন। এখন, লোকেরা জেআর নাম পরিবর্তন করতে গেলে ...
থমাস ওপেনস

@ থমাস: ধরেই নেওয়া হচ্ছে আপনি বর্তমান ডিরেক্টরি থেকে অ্যাপটি চালাচ্ছেন। "জাভা -জার ফু / বার / বাজ.জার" এর সাথে কী সমস্যা?
জন স্কিটি

আমি বিশ্বাস করি (এবং যাচাই করতে হবে), আপনার জারটিতে যদি কোডটি থাকে new File("baz.jar)তবে ফাইল অবজেক্টটি আপনার জার ফাইলটি উপস্থাপন করবে।
থমাস

@ থমাস: আমি এটি বিশ্বাস করি না। আমি বিশ্বাস করি এটি প্রক্রিয়াটির বর্তমান ওয়ার্কিং ডিরেক্টরিের সাথে আপেক্ষিক হবে। যদিও আমাকে আরও চেক করতে হবে :)
জন স্কিটি

3

কিছু সময় আগে আমি একটি ফাংশন করেছি যা জেআর এর ভিতর থেকে সংঘাত পেয়েছে:

public static Class[] getClasses(String packageName) 
throws ClassNotFoundException{
    ArrayList<Class> classes = new ArrayList<Class> ();

    packageName = packageName.replaceAll("\\." , "/");
    File f = new File(jarName);
    if(f.exists()){
        try{
            JarInputStream jarFile = new JarInputStream(
                    new FileInputStream (jarName));
            JarEntry jarEntry;

            while(true) {
                jarEntry=jarFile.getNextJarEntry ();
                if(jarEntry == null){
                    break;
                }
                if((jarEntry.getName ().startsWith (packageName)) &&
                        (jarEntry.getName ().endsWith (".class")) ) {
                    classes.add(Class.forName(jarEntry.getName().
                            replaceAll("/", "\\.").
                            substring(0, jarEntry.getName().length() - 6)));
                }
            }
        }
        catch( Exception e){
            e.printStackTrace ();
        }
        Class[] classesA = new Class[classes.size()];
        classes.toArray(classesA);
        return classesA;
    }else
        return null;
}

2
public static ArrayList<String> listItems(String path) throws Exception{
    InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
    byte[] b = new byte[in.available()];
    in.read(b);
    String data = new String(b);
    String[] s = data.split("\n");
    List<String> a = Arrays.asList(s);
    ArrayList<String> m = new ArrayList<>(a);
    return m;
}

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

যখন আমরা একটি জার ফাইল থেকে কোডটি কার্যকর করি তখন ডেটা খালি থাকে।
Aguid

1

দুটি অত্যন্ত দরকারী ইউটিলিটি উভয়ই জারস্ক্যান নামে পরিচিত:

  1. www.inetfeedback.com/jarscan

  2. jarscan.dev.java.net

এই প্রশ্নটি আরও দেখুন: জারস্ক্যান, নির্দিষ্ট শ্রেণীর জন্য সমস্ত সাবফোল্ডারে সমস্ত জেআর ফাইল স্ক্যান করুন


1

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

আমার প্রধান শ্রেণি যেখানে থাকে সেই জেআর ফাইলের নাম কীভাবে জানব?

URI mainClasspathElementURI;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("x.y.z")
        .enableClassInfo().scan()) {
    mainClasspathElementURI =
            scanResult.getClassInfo("x.y.z.MainClass").getClasspathElementURI();
}

আমি কীভাবে কোনও JAR ফাইলের মধ্যে একটি অনুরূপ ফ্যাশনে ডিরেক্টরিগুলির বিষয়বস্তু পড়তে পারি?

List<String> classpathElementResourcePaths;
try (ScanResult scanResult = new ClassGraph().overrideClasspath(mainClasspathElementURI)
        .scan()) {
    classpathElementResourcePaths = scanResult.getAllResources().getPaths();
}

আছে সম্পদ সঙ্গে মোকাবেলা করতে অন্য কোন উপায়ে প্রচুর খুব।


1
খুব ভাল প্যাকেজ, আমার স্কালা প্রকল্পে সহজেই ব্যবহারযোগ্য, আপনাকে ধন্যবাদ।
zslim

0

একটি জার ইউআরএল থেকে ফাইল তালিকাভুক্ত / পঠন করার এক ভিন্ন উপায় এবং এটি নেস্টেড জারগুলির জন্য এটি পুনরাবৃত্তভাবে করে

https://gist.github.com/trung/2cd90faab7f75b3bcbaa

URL urlResource = Thead.currentThread().getContextClassLoader().getResource("foo");
JarReader.read(urlResource, new InputStreamCallback() {
    @Override
    public void onFile(String name, InputStream is) throws IOException {
        // got file name and content stream 
    }
});

0

রাস্তার জন্য আরও একটি:

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;

import static java.nio.file.FileSystems.newFileSystem;
import static java.util.Collections.emptyMap;

public class ResourceWalker {
  private static final PathMatcher FILE_MATCHER =
      FileSystems.getDefault().getPathMatcher( "glob:**.ttf" );

  public static List<Path> walk( final String directory )
      throws URISyntaxException, IOException {
    final List<Path> filenames = new ArrayList<>();
    final var resource = ResourceWalker.class.getResource( directory );

    if( resource != null ) {
      final var uri = resource.toURI();
      final var path = uri.getScheme().equals( "jar" )
          ? newFileSystem( uri, emptyMap() ).getPath( directory )
          : Paths.get( uri );
      final var walk = Files.walk( path, 10 );

      for( final var it = walk.iterator(); it.hasNext(); ) {
        final Path p = it.next();
        if( FILE_MATCHER.matches( p ) ) {
          filenames.add( p );
        }
      }
    }

    return filenames;
  }
}

নির্দিষ্ট ফাইলের সাথে মিলে যাওয়ার জন্য এটি কিছুটা নমনীয় কারণ এটি ওয়াইল্ডকার্ড গ্লোববিং ব্যবহার করে।


আরও কার্যকরী শৈলী:

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.function.Consumer;

import static java.nio.file.FileSystems.newFileSystem;
import static java.util.Collections.emptyMap;

/**
 * Responsible for finding file resources.
 */
public class ResourceWalker {
  private static final PathMatcher FILE_MATCHER =
      FileSystems.getDefault().getPathMatcher( "glob:**.ttf" );

  public static void walk( final String dirName, final Consumer<Path> f )
      throws URISyntaxException, IOException {
    final var resource = ResourceWalker.class.getResource( dirName );

    if( resource != null ) {
      final var uri = resource.toURI();
      final var path = uri.getScheme().equals( "jar" )
          ? newFileSystem( uri, emptyMap() ).getPath( dirName )
          : Paths.get( uri );
      final var walk = Files.walk( path, 10 );

      for( final var it = walk.iterator(); it.hasNext(); ) {
        final Path p = it.next();
        if( FILE_MATCHER.matches( p ) ) {
          f.accept( p );
        }
      }
    }
  }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.