my problem is that I create a folder(name is IconResources) under src , in IconResources there are many pictures. Directory is like this:
I want to list all picture files name and do something with those pictures. And I found that File.list() only works in IDE, if I export project to a jar to make a standalone, it cannot work. So I searched and found that I should use inputstream and outputstream. Now I find i/o stream can works well for single file. But I want to use inputstream and outputstream to read folder(IconResource), then list the files in that folder.
So my question is how to use i/o put stream to load a folder and iterate the folder to list file names in that folder. These things should work under not only IDE but also exported jar. My code are follows:
private void initalizeIconFiles(File projectDirectory){
URL a = editor.getClass().getResource("/IconResources/");// Get Folder URL
List<String> iconFileNames=new ArrayList<String>();//Create a list to store file names from IconResource Folder
File iconFolder = new File(a.getFile());
Path path=Paths.get(iconFolder.getPath());
DirectoryStream<Path> stream = Files.newDirectoryStream(path) ;
for (Path entry : stream) {
if (!Files.isDirectory(entry)) {
System.out.println(entry.getFileName().toString());
iconFileNames.add(entry.getFileName().toString());// add file name in to name list
}
}
}
above code only can run under IDE but break down in exported jar.
What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.
Given an actual JAR file, you can list the contents using JarFile. entries() . You will need to know the location of the JAR file though - you can't just ask the classloader to list everything it could get at. You should be able to work out the location of the JAR file based on the URL returned from ThisClassName.
The List() method. This method returns a String array which contains the names of all the files and directories in the path represented by the current (File) object. Using this method, you can just print the names of the files and directories.
List Files. List all the files inside the JAR without extracting it. This can be done using either command jar , unzip or vim . Using unzip command in normal mode: list ( -l ) archive files in short format.
This is actually a very difficult question, as the ClassLoader
has to take account of the fact that you might have another folder called IconResources
on the classpath at runtime.
As such, there is no "official" way to list an entire folder from the classpath. The solution I give below is a hack and currently works with the implementation of URLClassLoader
. This is subject to change.
If you want to robust approach, you will need to use a classpath scanner. There are many of these in library form, my personal favourite is Reflections, but Spring has one built in and there are many other options.
Onto the hack.
Generally, if you getResourceAsStream
on a URLClassLoader
then it will return a stream of the resources in that folder, one on each line. The URLClassLoader
is the default used by the JRE so this approach should work out of the box, if you're not changing that behaviour.
Assume I have a project with the following classpath structure:
/
text/
one.txt
two.txt
Then running the following code:
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try(
final InputStream is = loader.getResourceAsStream("text");
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
Will print:
one.txt
two.txt
So, in order to get a List<URL>
of the resources in that location you could use a method such as:
public static List<URL> getResources(final String path) throws IOException {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try (
final InputStream is = loader.getResourceAsStream(path);
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
return br.lines()
.map(l -> path + "/" + l)
.map(r -> loader.getResource(r))
.collect(toList());
}
}
Now remember, these URL
locations are opaque. They cannot be treated as files, as they might be inside a .jar
or they might even be at an internet location. So in order to read the contents of the resource, use the appropriate methods on URL
:
final URL resource = ...
try(final InputStream is = resource.openStream()) {
//do stuff
}
You can read contents of a JAR file with JARInputStream
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With