No Such File exception in Runnable Jar file - java

I am trying to create a runnable jar file. My project includes models.txt file. My project works perfectly in eclipse with no error but when exported to a runnable jar file, It doesn't work. I hereby attach the error and the piece of code where the file is been called.
public static HashMap<String, RenderModel> getModelList(String file) throws IOException {
List<String> data;
HashMap<String, RenderModel> namesToModels = new HashMap<String, RenderModel>();
if (file != null) {
data = Files.readAllLines(Paths.get(file), StandardCharsets.UTF_8);
} else {
String path = "models/models.txt";
data = Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8);
}
Iterator<String> dataIterator = data.iterator();
while (dataIterator.hasNext()) {
String dataLine = dataIterator.next();
System.out.println(dataLine);
String[] line = dataLine.split("; ");
String key = line[0];
String valueObj = line[1];
String valueMtl = line[2];
float scale = Float.parseFloat((String) line[3]);
RenderModel v = new RenderModel(valueObj, valueMtl, scale);
namesToModels.put(key, v);
}
RenderModel v = new RenderModel("custom", "custom", 1.0f);
namesToModels.put("Choose Model from file", v);
return namesToModels;
}
Error Image:

If the files are in the Jar and you cannot read them, try accessing the files by doing:
getClass().getClassLoader().getResource(fileName);
Use this instead for static methods:
ClassName.class.getClassLoader().getResource(fileName);
Where fileName is the name of the file and ClassName the name of the class from which the statement is called.

In your code the path of the model.txt is 'src/models/model.txt'. When your project is packaged the src folder is not included usually. Then you must change the file location; could be better put the file outside the jar, but inside the java classpath.

It does not work because you do not have any file on the path src/models/models.txt when you run your jar else where, this path is only present in your IDE (ofcourse you can place your jar in a location from where it can reach that path, but this is not how it is supposed to be), when you package your project into a jar file it is packed in the package models and you can if you want to have it as default file read it via classpath.

Related

Java 8: How to copy files written in a list to a TXT file from one directory to another directory?

I have a simple text file called small_reports.txt that looks like:
report_2021_05_02.csv
report_2021_05_05.csv
report_2021_06_08.csv
report_2021_06_25.csv
report_2021_07_02.csv
This reported is generated with my java code and takes in each of these files from the directory /work/dir1/reports and writes them into the file combined_reports.txt and then places the txt file back into /work/dir1/reports.
My question is, for each line in small_reports.txt, find that same file (line) in /work/dir1/reports and then COPY them to a new directory called /work/dir1/smallreports?
Using Java 8 & NIO (which is really helpful and good) I have tried:
Path source = Paths.get("/work/dir1/reports/combined_reports.txt");
Path target = Paths.get("/work/dir1/smallreports/", "combined_reports.txt");
if (Files.notExists(target) && target != null) {
Files.createDirectories(Paths.get(target.toString()));
}
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
But this is just copying the actual txt file combined_reports.txt into the new directory and not the contents inside like i thought it would.
final String SOURCE_DIR = "/tmp";
final String TARGET_DIR = "/tmp/root/delme";
List<String> csvFileNames = Files.readAllLines(FileSystems.getDefault().getPath("small_reports.txt"), Charset.forName("UTF-8"));
for (String csvFileName : csvFileNames) {
Path source = Paths.get(SOURCE_DIR, csvFileName);
Path target = Paths.get(TARGET_DIR, csvFileName);
if (Files.notExists(target) && target != null) {
Files.createDirectories(Paths.get(target.toString()));
}
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
}
Should do it for you. Obviously change the constants appropriately

Random file from a folder inside JAR

I want to get a random image from a specific folder in Java. The code does already work inside the Eclipse IDE, but not in my runnable JAR. Since images inside the JAR file are not files, the code below results in a NullPointerException, but I'm not sure how to "translate" the code so that it will work in a runnable JAR.
final File dir = new File("images/");
File[] files = dir.listFiles();
Random rand = new Random();
File file = files[rand.nextInt(files.length)];
If the given path is invalid then listFiles() method reutrns null value. So you have to handle it if the path is invalid. Check below code:
final File dir = new File("images/");
File[] files = dir.listFiles();
Random rand = new Random();
File file = null;
if (files != null) {
file = files[rand.nextInt(files.length)];
}
If the jar is to contain the images then (assuming a maven or gradle project) they should be in the resources directory (or a subdirectory thereof). These images are then indeed no 'Files' but 'Resources' and should be loaded using getClass().getResource(String name) or getClass.getResourceAsStream(String name).
You could create a text file listing the resource paths of the images. This would allow you to simply read all lines from that file and access the resource via Class.getResource.
You could even create such a list automatically. The following works for my project type in eclipse; some minor adjustments may be needed for your IDE.
private static void writeResourceCatalog(Path resourcePath, Path targetFile) throws IOException {
URI uri = resourcePath.toUri();
try (BufferedWriter writer = Files.newBufferedWriter(targetFile, StandardCharsets.UTF_8)) {
Files.list(resourcePath.resolve("images")).filter(Files::isRegularFile).forEach(p -> {
try {
writer.append('/').append(uri.relativize(p.toUri()).toString()).append('\n');
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
writeResourceCatalog(Paths.get("src", "main", "resources"), Paths.get("src", "main", "resources", "catalog.txt"));
After building the jar with the new file included you could simply list all the files as
List<URL> urls = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(WriteTest.class.getResourceAsStream("/catalog.txt"), StandardCharsets.UTF_8))) {
String s;
while ((s = reader.readLine()) != null) {
urls.add(SomeType.class.getResource(s));
}
}
It seem like a path Problem, maybe will work if tried absolute path for image directory or set maon directory for java configuration

How to access files in a specified existing folder in src directory?

I have a folder called "all_users" in my java project under the src directory.How can I access the files(if there are any) in the all_users folder. I eventually want to loop through all the existing files in the "all_users" folder, comparing whether the file name is equal to a string i specify in the code.
Firstly, I tried File f = new File(System.getProperty("user.home")+File.pathSeparator + "all_users"); as the file object then later tried File dir = new File(TEST_PATH); Both returned false when i checked if it existed so i didn't set up the path correctly?
public class ValUtility {
static final String TEST_PATH = "./all_users/";
public static boolean validUsername(String user) {
File f = new File(System.getProperty("user.home") + File.pathSeparator + "all_users");
File dir = new File(TEST_PATH);
File[] directoryListing = f.listFiles();
System.out.println(f.exists());
System.out.println(directoryListing);
if (directoryListing != null) {
for (File child : directoryListing) {
// Do something with child
// think child is filename?
if (user.equals(child.getName())){
return false;
}
}
}
return true;
}
}
Please run...
System.out.println(System.getProperty("user.home"));
The above will inform you where you need to add a folder labeled 'all_users'. It is very unlikely that your 'user.home' property is set to your project's source file (src) folder.

How to get spring boot application jar parent folder path dynamically?

I have a spring boot web application which I run using java -jar application.jar. I need to get the jar parent folder path dynamically from the code. How can I accomplish that?
I have already tried this, but without success.
Well, what have worked for me was an adaptation of this answer.
The code is:
if you run using java -jar myapp.jar dirtyPath will be something close
to this: jar:file:/D:/arquivos/repositorio/myapp/trunk/target/myapp-1.0.3-RELEASE.jar!/BOOT-INF/classes!/br/com/cancastilho/service.
Or if you run from Spring Tools Suit, something like this:
file:/D:/arquivos/repositorio/myapp/trunk/target/classes/br/com/cancastilho/service
public String getParentDirectoryFromJar() {
String dirtyPath = getClass().getResource("").toString();
String jarPath = dirtyPath.replaceAll("^.*file:/", ""); //removes file:/ and everything before it
jarPath = jarPath.replaceAll("jar!.*", "jar"); //removes everything after .jar, if .jar exists in dirtyPath
jarPath = jarPath.replaceAll("%20", " "); //necessary if path has spaces within
if (!jarPath.endsWith(".jar")) { // this is needed if you plan to run the app using Spring Tools Suit play button.
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
}
String directoryPath = Paths.get(jarPath).getParent().toString(); //Paths - from java 8
return directoryPath;
}
EDIT:
Actually, if your using spring boot, you could just use the ApplicationHome class like this:
ApplicationHome home = new ApplicationHome(MyMainSpringBootApplication.class);
home.getDir(); // returns the folder where the jar is. This is what I wanted.
home.getSource(); // returns the jar absolute path.
File file = new File(".");
logger.debug(file.getAbsolutePath());
This worked for me to get the path where my jar is running, I hope this is what you are expecting.
Try this code
public static String getParentRealPath(URI uri) throws URISyntaxException {
if (!"jar".equals(uri.getScheme()))
return new File(uri).getParent();
do {
uri = new URI(uri.getSchemeSpecificPart());
} while ("jar".equals(uri.getScheme()));
File file = new File(uri);
do {
while (!file.getName().endsWith(".jar!"))
file = file.getParentFile();
String path = file.toURI().toString();
uri = new URI(path.substring(0, path.length() - 1));
file = new File(uri);
} while (!file.exists());
return file.getParent();
}
URI uri = clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
System.out.println(getParentRealPath(uri));

How do I create a String array with its elements being all the png files located in a resource folder?

I am trying to create a method that searches inside a folder for .png files and returns a String array with the respective path to each file. It must look inside a resource folder placed NOT in the src, but in project.
The following code works when running from within Eclipse:
// Analyzes specified folder and returns a file array
// populated with the .png files found in that folder
private File[] imageReader(String filePath) {
File folder = new File(filePath);
return folder.listFiles (new FilenameFilter() {
public boolean accept(File filePath, String filename)
{ return filename.endsWith(".png"); }
});
}
// Converts the file array into a string array
private String[] listPngFiles(String filePath) {
File[] imagesFileArray = imageReader(filePath); // file array
String[] imagesStringArray = new String[imagesFileArray.length];
for(int i=0; i<imagesFileArray.length; i++) {
imagesStringArray[i] = "" + imagesFileArray[i];
imagesStringArray[i] = imagesStringArray[i].substring(6); // discards "/images" from directory string
}
return imagesStringArray;
}
However it is not working when I run the exported executable JAR file. This is my current project setup:
.
I have tried the following code but it did not work either:
ClassLoader classLoader = getClass().getClassLoader();
File folder = new File(classLoader.getResource(filePath).getFile());
The reason I am doing this is because I want to have a JButton display an icon chosen from one of the sub folders inside the images resource folder. My JButton already has the following code:
.setIcon(new ImageIcon(GameLogic.class.getResource(**insert listPngFiles array element here**)));
Your help on the matter would be greatly appreciated.
You can achieve this by using Reflections, take a look at getResources

Categories