How can I count the number of files in a folder within a JAR?
I've spent a bit of time trying to find a way to count the number of files in a folder within a JAR. I put together several examples of code that served different purposes to make this work. It counts just fine when I run the code through Eclipse but after exporting to a JAR it fails and returns 0. In this case, my folder path I use is just "rules/". I would appreciate any recommendations or samples. Thanks.
public static int countFiles(String folderPath) throws IOException { //Counts the number of files in a specified folder
ClassLoader loader = ToolSet.class.getClassLoader();
InputStream is = loader.getResourceAsStream(folderPath);
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
boolean empty = true;
while ((readChars = is.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
}
return (count == 0 && !empty) ? 1 : count;
} finally {
is.close();
}
}
EDIT: The following doesn't exactly match my original question but thanks to MadProgrammer I was able to reduce my code and eliminate the need to even count the files. The code blow searches every file in my JAR looking for those that end with ".rules", opens the file, searches the file for a string that matches "searchBox.getText()", appends results, and continues on to the next ".rules" file.
StringBuilder results = new StringBuilder();
int count = 0;
JarFile jf = null;
try {
String path = ToolSet.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
jf = new JarFile(new File(decodedPath));
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(".rules")) {
String name = entry.getName();
InputStream in = ToolSet.class.getResourceAsStream(name);
InputStreamReader isr = new InputStreamReader(in);
BufferedReader bf = new BufferedReader(isr);
String line;
while ((line = bf.readLine()) != null) {
String lowerText = line.toLowerCase();
if(lowerText.indexOf(searchBox.getText().toLowerCase()) > 0) {
results.append(line + "\n");
count++;
}
}
bf.close();
}
}
} catch (IOException ex) {
try {
jf.close();
} catch (Exception e2) {
}
}
if(count>0) {
logBox.setText(results.toString());
} else {
logBox.setText("No matches could be found");
}
A Jar file is essentially a Zip file with a manifest.
Jar/Zip files don't actually have a concept of directories like disks do. They simply have a list of entries that have names. These names may contain some kind path separator and some entries may actually be marked as directories (and tend not to have any bytes associated with them, merely acting as markers)
If you want to find all the resources within a given path, you're going to have to open the Jar file and inspect it's entries yourself, for example...
JarFile jf = null;
try {
String path = "resources";
jf = new JarFile(new File("dist/ResourceFolderCounter.jar"));
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.isDirectory()) {
String name = entry.getName();
name = name.replace(path + "/", "");
if (!name.contains("/")) {
System.out.println(name);
}
}
}
} catch (IOException ex) {
try {
jf.close();
} catch (Exception e) {
}
}
Now, this requires you to know the name of the Jar file you want to use, this may be problematic, as you may wish to list resources from a number of different Jars...
A better solution would be to generate some kind of "resource lookup" file at build time, which contained all the names of the resources that you might need, maybe even keyed to particular names...
This way you could simple use...
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsInputStream("/resources/MasterResourceList.txt")));
String name = null;
while ((name = br.readLine()) != null) {
URL url = getClass().getResource(name);
}
} finally {
try {
br.close();
} catch (Exception exp) {
}
}
For example...
You could even seed the file with the number of resources ;)