How do I get the path of a an executed .jar file, in Java?
I tried using System.getProperty("user.dir"); but this only gave me the current working directory which is wrong, I need the path to the directory, that the .jar file is located in, directly, not the "pwd".
Could you specify why you need the path?If you need to access some property from the jar file you should have a look at ClassLoader.getSystemClassLoader();
don't forget that your classes are not necessary store in a jar file.
// if your config.ini file is in the com package.
URL url = getClass().getClassLoader().getResource("com/config.ini");
System.out.println("URL=" + url);
InputStream is = getClass().getClassLoader().getResourceAsStream("com/config.ini");
try {
if (is != null) {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
else {
System.out.println("resource not found.");
}
}
catch (IOException e) {
e.printStackTrace();
}
regards.
Taken From Java-Forumns:
public static String getPathToJarfileDir(Object classToUse) {
String url = classToUse.getClass().getResource("/" + classToUse.getClass().getName().replaceAll("\\.", "/") + ".class").toString();
url = url.substring(4).replaceFirst("/[^/]+\\.jar!.*$", "/");
try {
File dir = new File(new URL(url).toURI());
url = dir.getAbsolutePath();
} catch (MalformedURLException mue) {
url = null;
} catch (URISyntaxException ue) {
url = null;
}
return url;
}
Perhaps java.class.path property?
If you know the name of your jar file, and if it is in the class path, you can find its path there, eg. with a little regex.
Related
This spring app performs simple file upload,
here's the controller class
#Override
public String fileUpload(MultipartFile file) {
try{
// save uploaded image to images folder in root dir
Files.write(Paths.get("images/"+ file.getOriginalFilename()), file.getBytes());
// perform some tasks on image
return "";
} catch (IOException ioException) {
return "File upload has failed.";
} finally {
Files.delete(Paths.get("images/" + file.getOriginalFilename()));
}
}
but when i build jar and runs, it throws IOException saying,
java.nio.file.NoSuchFileException: images\8c9.jpeg.
So my question is how can i add the images folder inside the jar executable itself.
Thanks.
You should provide a full path for the images folder, or save in java.io.tmpdir creating the image folder first.
But, in my opinion you should configure your upload folder from a config file for flexibility. Take a look at this.
app:
profile-image:
upload-dir: C:\\projs\\web\\profile_image
file-types: jpg, JPG, png, PNG
width-height: 360, 360
max-size: 5242880
In your service or controller, do whatever you like, may be validate image type, size etc and process it as you like. For instance, if you want thumbnails(or avatar..).
In your controller or service class, get the directory:
#Value("${app.image-upload-dir:../images}")
private String imageUploadDir;
Finally,
public static Path uploadFileToPath(String fullFileName, String uploadDir, byte[] filecontent) throws IOException {
Path fileOut = null;
try{
Path fileAbsolutePath = Paths.get(StringUtils.join(uploadDir, File.separatorChar, fullFileName));
fileOut = Files.write(fileAbsolutePath, filecontent);
}catch (Exception e) {
throw e;
}
return fileOut; //full path of the file
}
For your question in the comment: You can use java.io.File.deleteOnExit() method, which deletes the file or directory defined by the abstract path name when the virtual machine terminates. TAKE A GOOD CARE THOUGH, it might leave some files if not handled properly.
try (ByteArrayOutputStream output = new ByteArrayOutputStream();){
URL fileUrl = new URL(url);
String tempDir = System.getProperty("java.io.tmpdir");
String path = tempDir + new Date().getTime() + ".jpg"; // note file extension
java.io.File file = new java.io.File(path);
file.deleteOnExit();
inputStream = fileUrl.openStream();
ByteStreams.copy(inputStream, output); // ByteStreams - Guava
outputStream = new FileOutputStream(file);
output.writeTo(outputStream);
outputStream.flush();
return file;
} catch (Exception e) {
throw e;
} finally {
try {
if(inputStream != null) {
inputStream.close();
}
if(outputStream != null) {
outputStream.close();
}
} catch(Exception e){
//skip
}
}
I have a custom java server. It uses an external xml config file.
I have some command line options to help the user, the usual stuff for showing a help file, setting ports, etc...
I've recently added a command to generate a default config file for the server. It's an xml file. After researching my options, packing a default xml file in the jar seemed to be the way to go, but I'm obviously missing something.
So far my code looks like this:
public class ResourceLoader {
private File outFile = null;
private Reader fileReader = null;
private Writer fileWriter = null;
private InputStream is = null;
private char[] buffer = null;
public ResourceLoader() {
outFile = new File("default-server.xml");
}
public void generateDefaultServerXml() {
is = ResourceLoader.class.getResourceAsStream("/default-server.xml");
if (is == null) {
System.out.println("Configuraiton File generation failed. The InputStream is null.");
} else {
fileReader = new InputStreamReader(is);
}
buffer = new char[4096];
FileOutputStream fos;
try {
fos = new FileOutputStream(outFile);
fileWriter = new OutputStreamWriter(fos);
while (fileReader.read(buffer) != -1) {
fileWriter.write(buffer, 0, buffer.length);
fileWriter.flush();
buffer = new char[4096];
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fileReader.close();
fileWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The code above works perfectly fine when I run it in eclipse, but intitially, after I export the jar file the server could not locate the default-server.xml file when I run the command from the terminal.
The file itself is located in a package called main.resources along with some other config files and the above class.
I have since moved the ResourceLoader.class to another package. After doing that the server seems to find the xml file in the main.resources package (InputStream is not null) but the resulting generated default-server.xml file is empty.
Again, this all works perfectly well when I run it in eclipse, it's only after I export the project and try issue the command from the terminal that the process fails. What am I doing wrong?
The above class is instantiated, and the generateDefaultServerXml() is called, from the main method of the server.
EDIT: My path for writing default-server.xml was slightly wrong. Now that I've adjusted it the code works exactly as expected when I run it in Eclipse. The resource is read in the correct way, and written to the file in the correct location. But it still doesn't work when I try the same thing from the jar file.
You current line ResourceLoader.class.getResourceAsStream("/default-server.xml") means that you are trying to load a resource named default-server.xml from the root of your classpath, or put simpler, from the root of your jar file. This means that xml file should NOT be in any package inside the jar file.
When you assemble your jar file and then run jar tf my.jar on it, do you see your default-server.xml file? Does it reside in some package or in the root of the jar file?
The problem here is since you are packaging the application as a jar. The procedure to call an external resource is quite different.
You need to have a folder structure as
root
--your jar
--your xml file
Your code shallwork if the application is using an default-server.xml file inside the jar.
Otherwise, Replace below line in your code if you want to use an external default xml file.
is = new FileInputStream("./default-server.xml");
If the output file you want at root location the use below code
public ResourceLoader() {
outFile = new File("./default-server.xml");
}
Alternate code as per discussion
public class ResourceLoader {
public void generateDefaultServerXml() {
try {
String defaultxmltext =readFileToString("/default-server.xml");
writeFileFromInputString(defaultxmltext);
} catch (IOException e) {
//exception
}
}
public static void writeFileFromInputString(String everything) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("./default-server.xml"))) {
everything = everything.replaceAll("\n", System.getProperty("line.separator"));
writer.write(everything);
}
}
public static String readFileToString(String path) throws IOException {
String everything = null;
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
everything = sb.toString();
}
return everything;
}
}
Hope this helps
consider your file located on src/main/resources try this
getClass().getClassLoader().getResource(fileName)
well as far as i can see your main problem is that you are passing the wrong path, since you mentioned the xml is under main.resources you will need to add this to the path when trying to load the file, here is a sample piece of code that should work for you
Scanner sc = null;
PrintWriter writer = null;
try {
sc = new Scanner(getClass().getResourceAsStream("main/resources/server.xml"));
writer = new PrintWriter("./default_server.xml", "UTF-8");
while(sc.hasNextLine()) {
writer.println(sc.nextLine());
}
} catch (Exception e) {
} finally {
if(sc != null) {
sc.close();
}
if(writer != null){
writer.close();
}
}
I have a file named InputFile.txt in a resources folder.
My project structure is like this:
VirtualMemory
src
resources
InputFile.txt
VirtualMemory
VirtualMemory.java
And I am trying to access the InputFile.txt in VirtualMemory.java class by like this:
String filename = ("./src/resources/InputFile.txt");
File file = new File(filename);
But the file is not being found. How to resolve this problem?
Below code will help load a properties file from any where in the classpath.
ClassLoader cl = ClassLoader.getSystemClassLoader();
if (cl != null) {
URL url = cl.getResource(CONF_PROPERTIES);
if (url == null) {
url = cl.getResource("/" + CONF_PROPERTIES);
}
if (url != null) {
try {
InputStream in = url.openStream();
props = new Properties();
props.load(in);
} catch (IOException e) {
// Log the exception
} finally {
// close opened resources
}
}
}
I have to read a file which can be local or in remote.
The file path or URI will come form user input.
Currently I am reading only local file,this way
public String readFile(String fileName)
{
File file=new File(fileName);
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(file));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ( (line=bufferedReader.readLine())!=null ) {
stringBuilder.append(line);
stringBuilder.append(System.lineSeparator());
}
return stringBuilder.toString();
} catch (FileNotFoundException e) {
System.err.println("File : \""+file.getAbsolutePath()+"\" Not found");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
The parameter String fileName is the user input which can be a path to local file or a URI
How can i modify this method to work with both Local path and URI ?
Suposing you have the URI in String fileName you can read url easily with:
URI uri = new URI(filename);
File f = new File(uri);
Check this link for further info
File class has also a constructor based on the URI so it easy to say new File(uri).. and everything stays the same.
However, the URI is system-dependent, as specification says "An absolute, hierarchical URI with a scheme equal to "file", a non-empty path component, and undefined authority, query, and fragment components".
I think that if you need to read something remote, the best way to do it is by using Sockets.
How to call application servlet from java class with relative path.
I want to call with GET method
/myServlet
from
myClass.
EDIT
So far i find:
BufferedReader in = null;
URL url = null;
try {
url = new URL("http://localhost:8080/myApp/myServlet");
in = new BufferedReader(new InputStreamReader(url.openStream()));
result = in.readLine();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) in.close();
} catch (IOException e) { }
}
but as i said i want to call a servlet with relative path. Not to decler hostname and appName.