When I use relative path, I can run my Java program from Eclipse. But when I run it as a JAR file, the path doesn't work anymore. In my src/components/SettingsWindow.java I have:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./src/files/profile.ser"));
I get a FileNotFoundException.
My file directory looks like this:
file directory
What I've tried:
String filePath = this.getClass().getResource("/files/profile.ser").toString();
String filePath = this.getClass().getResource("/files/profile.ser").getPath();
String filePath = this.getClass().getResource("/files/profile.ser").getFile().toString();
And I'd just put filePath in new FileInputStream(filePath) but none of these work and I still get a FileNotFoundException. When I System.out.println(filePath) it says: files/profile.ser
I'm trying to get the path of src/files/profile.ser while I'm in src/components/SettingsWindow.java
You can get the URL to the class:
String path =
String.join("/", getClass().getName().split(Pattern.quote(".")))
+ ".class";
URL url = getClass().getResource("/" + path);
which will either yield "file:/path/to/package/class.class" or "jar:/path/to/jar.jar!/package/class.class". You either can work with the URL or use
JarFile jar =
((JarURLConnection) url.openConnection()).getJarFile();
and use jar.getName() to get the path to parse to get your installation directory.
To get the current JAR file path I use:
public static String getJarFilePath() throws FileNotFoundException {
String path = getClass().getResource(getClass().getSimpleName() + ".class").getFile();
if(path.startsWith("/")) {
throw new FileNotFoundException("This is not a jar file: \n"+path);
}
if(path.lastIndexOf("!")!=-1) path = path.substring(path.lastIndexOf("!/")+2, path.length());
path = ClassLoader.getSystemClassLoader().getResource(path).getFile();
return path.substring(0, path.lastIndexOf('!')).replaceAll("%20", " ");
}
Related
I am facing a problem but have not able to solve it yet. Let me share what I have done till now. I tried to delete a file using java.nio.file packages. And below is my code.
// directory will be dynamically generated.
String directory = fileDirectory+ "//" + fileName;
Path path = Paths.get(directory);
if (Files.exists(path)) {
Files.delete(path);
}
I generated the path correctly. But when Files.exists(path) calls it return false. That's why file is not deleted. But if I generated the directory string by hard-coded than it works perfectly.
// hard-coded directory works perfectly.
String directory = "C://opt//tomcat//webapps//resources//images//sprite.jpg";
I also tried the another method Files.deleteIfExists(path);. Which check the both the file existence and delete the file.
The other packages org.apache.commons.io.FileUtils and java.io.File have tried. But can't resolve the issue.
Note: My application is in spring-boot. And I read the directory from the application.properties file for both save images and delete images.
EDIT:
file uploading I mean save into the directory is perfectly worked. But file deletion does not work.
application.properties
image.root.dir=images
image.root.save.dir=C:/opt/tomcat/webapps/resources/
in implementation file
#Value("${image.root.dir}")
private String UPLOADED_FOLDER;
#Value("${image.root.save.dir}")
private String saveDir;
String directory = saveDir + UPLOADED_FOLDER + "/" + fileName;
save file into directory
String directory = saveDir + UPLOADED_FOLDER + "/";
try {
byte[] bytes = file.getBytes();
Path path = Paths.get(directory);
if (!Files.exists(path)) {
Files.createDirectories(path);
}
path = Paths.get(directory, file.getOriginalFilename());
Files.write(path, bytes);
} catch (IOException e) {
logger.error("save image into directory : " + e);
}
String directory = fileDirectory+ "//" + fileName;
This is not the correct separator used between a directory and a file name, though it seems to work as well.
This means the problem is not the separator, but a mismatch between the code that you use to generate the path and this code. You're generating the directory into somewhere else than where this is pointing.
I try to read a resource file from my application but it doesn't work.
Code:
String filename = getClass().getClassLoader().getResource("test.xsd").getFile();
System.out.println(filename);
File file = new File(filename);
System.out.println(file.exists());
Output when I execute the jar-file:
file:/C:/Users/username/Repo/run/Application.jar!/test.xsd
false
It works when I run the application from IntelliJ but not when I execute the jar-file. If I open my jar-file with 7-zip test.xsd is located in the root-folder. Why isn't the code working when I execute the jar-file?
Also, File refers to actual OS file-system files; in the OS's file-system, there is only a jar file, and that jar file is not a folder. You should either extract the contents of the URL to a temporary file, or operate with its bytes in-memory or as a stream.
Note that myURL.getFile() is returning a String representation, and not an actual File. In a similar way, this will not work:
File f = new URL("http://www.example.com/docs/resource1.html").getFile();
f.exists(); // always false - will not be found in the local filesystem
A nice wrapper could be the following:
public static File openResourceAsTempFile(ClassLoader loader, String resourceName)
throws IOException {
Path tmpPath = Files.createTempFile(null, null);
try (InputStream is = loader.getResourceAsStream(resourceName)) {
Files.copy(is, tmpPath, StandardCopyOption.REPLACE_EXISTING);
return tmpPath.toFile();
} catch (Exception e) {
if (Files.exists(tmpPath)) Files.delete(tmpPath);
throw new IOException("Could not create temp file '" + tmpPath
+ "' for resource '" + resourceName + "': " + e, e);
}
}
I have a bit problem, and i dont seem to understand what is causing it.
i have a folder in my project, and in that folder i have a class, and i have a resource file (in this case jasper report).
but the only way i can access file is with absolute path or some path that starts from root of my project.
String path = "src/main/java/Views/LagerMain/lager.jrxml";
^^this works, both my class LagerController and lager.jrxml are under LagerMain folder, but when i try to do this :
String path = "lager.jrxml";
i have an error that file is not found.
I tried googling this to have a better understanding but i found nothing.
Bottom line, why cant i access my file, from class when they are both on same place, why does not relative path work.
If the main class is in a different directory, then the program will try to accesslager.jrxml there instead of the directory of the regular class.
For regular-class directory:
String path = new String(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
.getPath() + System.getProperty("line.separator") + "lager.jrxml");
If that doesn't work, try this:
// your directory
File f = new File("src");
File[] matchingFiles = f.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith("lager") && name.endsWith("jrxml");
}
});
If you have more than one file with the name lager.jrxml, then this method will return both of them and you will need to use a for to cycle through them. Otherwise, you can just use
String path = new String(matchingFiles[0].getAbsolutePath())
For main-class directory:
String path = new String(System.getProperty("user.dir")
+ System.getProperty("line.separator") + "lager.jrxml");
How to write or read any type of file (for example .txt file) to a resources folder with the config.property file, but without using absolute path file.
I tried to solve this like below:
ClassLoader classLoader = Setting.class.getClassLoader();
Setting setting = new Setting();
try (InputStream resourceAsStream = classLoader.getResourceAsStream("config.properties")) {
setting.load(resourceAsStream);
}
String readFileName = setting.getValue("pathSource.txt");
String writeFileName = setting.getValue("outPutPathSourceFile.txt");
String s = System.getProperty("line.separator");
File readFile = new File("./src/main/resources" + File.separator + "pathSource.txt");
File writeFile = new File("./src/main/resources" + File.separator + "outPutPathSourceFile.txt");
However, I don't want using ./src/main/resources prefix.
If your file is located under resources you able to access it like:
File file = new File(classLoader.getResource(fileName).getFile());
if you are using Spring you can use ResourceUtils.getFile():
File file = ResourceUtils.getFile("classpath:fileName")
UPDATE:
If I understand correctly, you want to read file which located under your src/main/resources without relative path usage /src/main/resources.
I created small demo:
public class ReadResourceFile {
public static void main(String[] args) throws IOException {
String fileName = "webAutomationConfig.xml";
ClassLoader classLoader = ReadResourceFile.class.getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
System.out.println("File exists: " + file.exists());
String content = new String(Files.readAllBytes(file.toPath()));
System.out.println(content);
}
}
Output:
File exists: true
<?xml version="1.0" encoding="utf-8"?>
<config>
<baseUrl>https://www.gmail.com</baseUrl>
</config>
Project structure:
Resources (files on the class path, possibly inside a jar)can be read, but are not intended to be written to. You can use them as template to create an inital copy on the file system. – Joop Eggen
url = new java.net.URL(s) doesn't work for me.
I have a string C:\apache-tomcat-6.0.29\webapps\XEPServlet\files\m1.fo and need to make a link and give it to my formatter for output, but malformed url recieved. It seems that it doesn't make my string to url.
I want also mention, that file m1.fo file is in files folder, in my webapp\product\, and I gave the full path to string like: getServletContext().getRealPath("files/m1.fo"). What I am doing wrong? How can I recieve the url link?
It is possible to get an URL from a file path with the java.io.File API :
String path = "C:\\apache-tomcat-6.0.29\\webapps\\XEPServlet\\files\\m1.fo";
File f = new File(path);
URL url = f.toURI().toURL();
Try: file:///C:/apache-tomcat-6.0.29/webapps/XEPServlet/files/m1.fo
It isn't preferable to write file:/// . Indeed it works on windows system,but in unix - there were problems.
Instead of using
myReq.put("xml", new String []{"file:" + System.getProperty("file.separator") +
getServletContext().getRealPath(DESTINATION_DIR_PATH) +
System.getProperty("file.separator") + xmlfile});
you can write
myReq.put("xml", new String [] {getUploadedFileURL (xmlfile)} );
, where
public String getUploadedFileURL(String filename) {
java.io.File filePath = new java.io.File(new
java.io.File(getServletContext().getRealPath(DESTINATION_DIR_PATH)),
filename);
return filePath.toURI().toURL().toString();
A file system path is not a URL. A URL is going to need a protocol prefix for one. To reference file system use "file:" in front of your path.