So, I used java.io.File for basically everything before.
But now, when switching to java.nio.Path, I'm experiencing a few problems...
What I use it for is basically loading/saving files, on my program startup and shutdown.
I use it in multiple places but I'll type an example:
Objects.requireNonNull(directory, "directory");
if (this.myObjectMap.isEmpty()) {
return;
}
Files.list(directory).forEach(file -> {
try {
Files.deleteIfExists(file);
} catch (IOException exception) {
exception.printStackTrace();
}
});
Files.createDirectories(directory);
for (Object object : this.myObjectMap.values()) {
Path destination = directory.resolve(object.toString() + ".json");
Files.deleteIfExists(destination);
Files.createFile(destination);
JsonObject properties = new JsonObject();
JSONFileHandler.save(destination, properties);
}
My problem is that everytime I do something similar to this, it throws a NoSuchFileException exception before even using the Path... But I don't know what I'm doing wrong, since I check if it exists after creating the Path.
Update
The exception stacktrace is the following:
java.nio.file.NoSuchFileException: **the directory**
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsDirectoryStream.<init>(WindowsDirectoryStream.java:86)
at sun.nio.fs.WindowsFileSystemProvider.newDirectoryStream(WindowsFileSystemProvider.java:518)
at java.nio.file.Files.newDirectoryStream(Files.java:457)
at java.nio.file.Files.list(Files.java:3451)
Here's the javadoc for Path, this is what it says:
An object that may be used to locate a file in a file system. It will
typically represent a system dependent file path.
So, a Path just represents a Path, it's not a pointer to an existing file or directory and hence, it may or may not exist.
In our example, we need to check whether the Path exists, before calling Files.list and that would make sure we are iterating through valid path, e.g.:
Path directory = Paths.get("some directory");
Objects.requireNonNull(directory, "directory");
if(Files.exists(directory)){
Files.list(directory).forEach(file -> {
try {
System.out.println(file);
} catch (Exception exception) {
exception.printStackTrace();
}
});
}
Related
I am coming to an issue where I am trying to check if output folder is there and if not create one in my code below. So, I tried doing that way as shown in my code but I dont know if its the proper a way of doing it? can you please advise. thanks for the help.
here is my code:
String outputFolder2 = Printer.getOutputFolder();
File outFileTwo = new File(outputFolder2);
if (!outFileTwo.exists()) {
if (!outFileTwo.mkdir()) {
System.out.println("Failed to make directory for: " + outputFolder2);
}
}
To check if the directory exists:
Files.isDirectory(Paths.get("/the/path"))
To create dir if not exists:
Files.createDirectories(Paths.get("/the/path"))
Simply use
dirPathFileObj.mkdir();
From java.io.File;
If the method detects that no such directory exists, it will automatically create one. Otherwise, it will simply do nothing in terms of File creation.
It's recommended to use the nio package for new code that interacts with files -- it's faster, and easier to code for. Here's how I would write that code, in the form of a junit test that I ran to verify it:
#Test
public void testSomething() {
Path dirPath = Paths.get("C:/I/do/not/exist");
Path filePath = dirPath.resolve("newFile.txt");
try {
assertFalse(Files.exists(dirPath));
dirPath = createDirectories(dirPath);
filePath = Files.createFile(filePath);
assertTrue(Files.exists(filePath));
} catch (IOException iox) {
iox.printStackTrace();
} finally {
try {
Files.deleteIfExists(filePath);
Files.deleteIfExists(dirPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This will create C:\I\do\not\exist\newFile.txt, then delete C:\I\do\not\exist, (leaving C:\I\do\not\). For production code, you'd want to remove the asserts and fill in those catch clauses
I've exported my Java console application to a Jar file, but when I run the jar and call code that parses in a JSON file I get a java.lang.IllegalArgumentException
Does anyone know why the exception is being thrown when I run the program as a JAR? The parsing works fine when the application is run from Eclipse.
This is the exact error that is output when I execute the jar file and call the code that parses the JSON file:
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierar
chical
at java.io.File.<init>(Unknown Source)
at gmit.GameParser.parse(GameParser.java:44)
at gmit.Main.main(Main.java:28)
This is how the parsing is being done in my GameParser class:
public class GameParser {
private static final String GAME_FILE = "/resources/game.json";
private URL sourceURL = getClass().getResource(GAME_FILE);
private int locationId;
private List<Location> locations;
private List<Item> items;
private List<Character> characters;
public void parse() throws IOException, URISyntaxException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
// read from file, convert it to Location class
Location loc = new Location();
loc = mapper.readValue(new File(sourceURL.toURI()), Location.class);
Item item = mapper.readValue(new File(sourceURL.toURI()), Item.class);
GameCharacter character = mapper.readValue(new File(sourceURL.toURI()), GameCharacter.class);
// display to console
System.out.println(loc.toString());
System.out.println(item.toString());
System.out.println(character.toString());
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the folder structure of my project:
The call getClass().getResource(GAME_FILE); will return a URL relative to this class. If you are executing your program from a JAR file, it will return a URL pointing to a JAR file.
Files in java can only represent direct filesystem files, not the ones in zip/jar archives.
To fix it:
Try to use getClass().getResourceAsStream() and use that instead of Files or
extract the files into some directory and use File in the same way as you are trying now.
This problem happen when you have two files with the same name,i mean in your project you have folder whith name "Images" and in your desktop you have other folder his name "images" automatically JVM choose desktop folder ,so if you want to confirm try to print your URI.Use this example to show your URI before creating your file
try {
URL location = this.getClass().getResource("/WavFile");
System.out.println(location.toURI());
File file = new File(location.toURI());
if (!file.exists()) {
System.out.println(file.mkdirs());
System.out.println(file.getAbsoluteFile());
}else
{
System.out.println(file.getPath());
}
} catch (Exception e) {
e.printStackTrace();
}
We have a legacy system that has a admim module that allows users to upload jar files. After the upload, the jar file is validated and if not compliant to internal rules, it is deleted.
The problem is that windows is throwing an exception telling that the file "is already being used by another process." (when I call Files.delete(tmpJar);). I'm not able to identify why the file is open. Seems to me that I have closed everything.
First, we are using primefaces (4.0) to upload the file. Primefaces relies on commons-fileupload (1.3.1). It call the following method:
public void handleFileUpload(FileUploadEvent event) {
Path tmpJar = null;
try {
tmpJar = Files.createFile(Paths.get(event.getFile().getFileName()));
Files.write(tmpJar, event.getFile().getContents());
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
if (tmpJar != null) {
try {
this.validateJar(tmpJar.toString());
Files.delete(tmpJar);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
Before NIO Files.write, I was using "standard" java IO classes. The problem isn't related to the above code, because if I comment the call to validateJar, Files.delete(tmpJar) is executed without problems and the file is removed. So, the problem is related with the code below, but I can't find where...
Job is an internal class, basically a simple POJO. "jobAnnotation" is a custom annotation to identify Jobs. I have shortened the code, but the essencial parts are preserved.
private List<Job> validateJar(final String jarPath) throws IOException {
List<Job> jobs = new ArrayList<Job>();
try (JarFile jarFile = new JarFile(jarPath)) {
URL[] jars = { new URL("file:" + jarPath) };
ClassLoader jobClassLoader = URLClassLoader.newInstance(jars, this.getClass().getClassLoader());
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String className = jarEntry.getName();
Class<?> classToLoad;
try {
classToLoad = Class.forName(className, true, jobClassLoader);
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
continue;
}
if (classToLoad.isAnnotationPresent(jobAnnotation)) {
String vlr = null;
try {
Class<?> jobClass = (Class<?>) Class.forName(classToLoad.getCanonicalName(), true, jobClassLoader);
Annotation annotation = jobClass.getAnnotation(jobAnnotation);
Method method = annotation.getClass().getMethod("getValue");
vlr = ((String) method.invoke(annotation, new Object[0]));
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
}
Job job = new Job();
job.setEnabled(true);
job.setJarfile(jarPath);
job.setClassName(classToLoad.getName());
Parameter parameter = new Parameter();
parameter.setRequired(true);
parameter.setName("name");
parameter.setValue(vlr);
job.addParameter(parameter);
jobs.add(job);
}
}
} catch (IOException e) {
throw e;
}
return jobs;
}
Before using try-with-resources, I was using regular try-catch-finally to close the JarFile, thats the only thing that has a explicit close method. Probably is the classloading that is holding the file open, but I don't know how to close it.
I did some searches, and I found that I can't unload classes (Unloading classes in java?).
So, the problem is, how do I release it? Or how can I remove the file?
BTW, I'm using java 1.7.0_71, jboss 7.1.1, windows 7 (64).
The URLClassLoader class already has a close() method. The close() method will close any Jar file that are opened with the URLClassLoader. This should prevent the "file already in use" exception.
File is already being used by another process. says that it could be not your fault, maybe just another application is used that file. You can check this question to find a process which is used your file.
Some Virus scanner software take a long time in checking JARs. Try to disable the Virusscanner. Other candidates can be the Windows indexer process, or the explorer.exe itself. When you don't find any reason for the file lock, try a delay between the validation and the deletion. Maybe you need a loop with multiple tries.
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
{
System.out.println("Sending Birthday Wishes... ");
try
{
for(int i=0;i<maillist.length;i++)
{
Email email = new Email();
email.setFrom("spv_it#yahoo.com");
email.setSubject("Happy IndependenceDay");
email.setTo(maillist[i]);
email.setText("<font color=blue><h4>Dear Users,<br><br><br>Wish you a Happy Independence Day!<br><br><br>Regards,<br>Penna Cement Industries Limited</h4></font>");
byte[] data = null;
ClassPathResource img = new ClassPathResource("newLogo.gif");
InputStream inputStream = img.getInputStream();
data = new byte[inputStream.available()];
while((inputStream.read(data)!=-1));
Attachment attachment = new Attachment(data, "HappyBirthDay","image/gif", true);
email.addAttachment(attachment);
emailService.sendEmail(email);
}
}
catch (MessagingException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
This is the error I'm getting:
java.io.FileNotFoundException: class path resource [newLogo.gif] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:135)
at com.mail.schedular.BirthdayWisherJob.executeInternal(BirthdayWisherJob.java:55)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:66)
at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
The best practise is to read/write or to provide reference of any file is by mentioning the ABSOLUTE PATH of that file.
To your question, It shows the FileNotFoundException because, JVM failed to locate the file in your current directory which is by default your source path. So provide the absolute path in ClassPathResource or copy that image file to your current directory. It will solve your problem.
I think you need to put your file inside inside the src folder , if it's there then check whether it's under some directory which is inside the src directory.
Then give the correct location like given details below
src[dir]----->newLogo.gif
ClassPathResource img = new ClassPathResource("newLogo.gif");
or,
src[dir]----->images[dir]---->newLogo.gif
ClassPathResource img = new ClassPathResource("/images/newLogo.gif");
You got this error since the job is running in a separate quartz thread, I suggest that you locate your file newLogo.gif outside the jar and use the following to load it.
Thread.currentThread().getContextClassLoader().getResource("classpath:image/newLogo.gif");
I am having a problem writing to a .xml file inside of my jar. When I use the following code inside of my Netbeans IDE, no error occurs and it writes to the file just fine.
public void saveSettings(){
Properties prop = new Properties();
FileOutputStream out;
try {
File file = new File(Duct.class.getResource("/Settings.xml").toURI());
out = new FileOutputStream(file);
prop.setProperty("LAST_FILE", getLastFile());
try {
prop.storeToXML(out,null);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.toString());
}
try {
out.close();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.toString());
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.toString());
}
}
However, when I execute the jar I get an error saying:
IllegalArguementException: uri is not hierachal
Does anyone have an idea of why it's working when i run it in Netbeans, but not working when i execute the jar. Also does anyone have a solution to the problem?
The default class loader expects the classpath to be static (so it can cache heavily), so this approach will not work.
You can put Settings.xml in the file system if you can get a suitable location to put it. This is most likely vendor and platform specific, but can be done.
Add the location of the Settings.xml to the classpath.
I was also struggling with this exception. But finally found out the solution.
When you use .toURI() it returns some thing like
D:/folderName/folderName/Settings.xml
and hence you get the exception "URI is not hierarchical"
To avoid this call the method getPath() on the URI returned, which returns something like
/D:/folderName/folderName/Settings.xml
which is now hierarchical.
In your case, the 5th line in your code should be
File file = new File(Duct.class.getResource("/Settings.xml").toURI().getPath());