My program loops through some folders and copies the files in the folder to a new file with a new name. Some files will copy and others will get a Java Exception saying access denied. When that happens the program terminates. I want it to skip and not copy that file and just keep going. Here is the copy function.
private static void copyFile(File source, File dest)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} catch (Exception e){
}
finally{
inputChannel.close();
outputChannel.close();
}
}
Any help would be great. Thanks!
Just catch the exception in the calling program to your copyFile method and continue on. The reason I removed the catch block in the copyFile method is it allows the copyFile method to be generally used (times when you might want to stop processing during an exception and times when you want to ignore the exception).
...
for (File source : sources) {
try {
copyFile(source, dest);
}
catch (Exception ignore) {
// ignore exception and continue
}
// do your other stuff here
}
private static void copyFile(File source, File dest)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
}
finally{
if (inputChannel != null) inputChannel.close();
if (outputChannel != null) outputChannel.close();
}
}
In your catch block, you can use a continue statement to "skip" the file currently being processed.
Something like below (also incorporates Prabhakaran's suggestion of null checking values):
private static void copyFile(File source, File dest)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} catch (Exception e) {
// You should be logging any exception here. Empty blocks == bad practice.
continue;
} finally {
if(inputChannel != null {
inputChannel.close();
}
if(outputChannel != null {
outputChannel.close();
}
}
}
change
finally{
inputChannel.close();
outputChannel.close();
}
to
finally{
try {
if(inputChannel!=null)
inputChannel.close();
if(outputChannel!=null)
outputChannel.close();
} catch (Exception e){
}
}
and remove the throws IOException from copyFile(File source, File dest) method
now your method look like this
private static void copyFile(File source, File dest){
}
Related
I'm trying to write code for a jarfile which if executed, it shutdowns the JVM and then deletes the jarfile. This is what I've tried to do so far but it is not deleting the file after the JVM closes.
public static void check() {
if (isJarFile()) {
try (Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())) {
String remote_hash = s.nextLine().trim();
File jarFile = getJarFile();
if (jarFile != null && !remote_hash.equals(getMD5Checksum(jarFile.getAbsolutePath()))) {
jarFile.setWritable(true);
jarFile.deleteOnExit();
}
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
public static byte[] createChecksum(String filename) throws Exception {
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
public static File getJarFile() {
try {
return new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
Can someone explain why deleteOnExit is not working in this instance?
Make sure that you close any stream that you have open on a file before exiting your JVM. Otherwise, the shut down hook that is supposed to delete the file cannot trigger on Windows as opening the stream triggers a file lock on the OS-level.
For your example, it means that you must not end the JVM process before exiting the try-with-ressources-block which is roughly translated into:
Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())
try {
// your code
System.exit(0);
} finally {
s.close(); // Never executed
}
As your program exits before the finally block is executed, the shut down hook is triggered without closing the stream and the file cannot be deleted.
Note that the following code will work for your purposes as the finally block is executed after closing the try-with-ressources argument:
try (Scanner s = new Scanner(new URL(HASH_PROVIDER).openStream())) {
// your code
} catch (Exception e) {
e.printStackTrace();
} finally {
System.exit(0);
}
Okay, this is going to be a bit long. So I made a junit test class to test my program. I wanted to test if a method that uses a Scanner to read a file into the program threw and exception, if the file didn't exist like this:
#Test
public void testLoadAsTextFileNotFound()
{
File fileToDelete = new File("StoredWebPage.txt");
if(fileToDelete.delete()==false) {
System.out.println("testLoadAsTextFileNotFound - failed");
fail("Could not delete file");
}
try{
assertTrue(tester.loadAsText() == 1);
System.out.println("testLoadAsTextFileNotFound - passed");
} catch(AssertionError e) {
System.out.println("testLoadAsTextFileNotFound - failed");
fail("Did not catch Exception");
}
}
But the test fails at "could not delete file", so I did some searching. The path is correct, I have permissions to the file because the program made it in the first place. So the only other option would be, that a stream to or from the file is still running. So I checked the method, and the other method that uses the file, and as far as I can, both streams are closed inside the methods.
protected String storedSite; //an instance variable
/**
* Store the instance variable as text in a file
*/
public void storeAsText()
{
PrintStream fileOut = null;
try{
File file = new File("StoredWebPage.txt");
if (!file.exists()) {
file.createNewFile();
}
fileOut = new PrintStream("StoredWebPage.txt");
fileOut.print(storedSite);
fileOut.flush();
fileOut.close();
} catch(Exception e) {
if(e instanceof FileNotFoundException) {
System.out.println("File not found");
}
fileOut.close();
} finally {
if(fileOut != null)
fileOut.close();
}
}
/**
* Loads the file into the program
*/
public int loadAsText()
{
storedSite = ""; //cleansing storedSite before new webpage is stored
Scanner fileLoader = null;
try {
fileLoader = new Scanner(new File("StoredWebPage.txt"));
String inputLine;
while((inputLine = fileLoader.nextLine()) != null)
storedSite = storedSite+inputLine;
fileLoader.close();
} catch(Exception e) {
if(e instanceof FileNotFoundException) {
System.out.println("File not found");
return 1;
}
System.out.println("an Exception was caught");
fileLoader.close();
} finally {
if(fileLoader!=null)
fileLoader.close();
}
return 0; //return value is for testing purposes only
}
I'm out of ideas. Why can't I delete my file?
EDIT: i've edited the code, but still this give me the same problem :S
You have two problems here. The first is that if an exception is thrown during your write to the file, the output stream is not closed (same for the read):
try {
OutputStream someOutput = /* a new stream */;
/* write */
someOutput.close();
The second problem is that if there's an exception you aren't notified:
} catch (Exception e) {
if (e instanceof FileNotFoundException) {
/* do something */
}
/* else eat it */
}
So the problem is almost certainly that some other exception is being thrown and you don't know about it.
The 'correct' idiom to close a stream is the following:
OutputStream someOutput = null;
try {
someOutput = /* a new stream */;
/* write */
} catch (Exception e) {
/* and do something with ALL exceptions */
} finally {
if (someOutput != null) someOutput.close();
}
Or in Java 7 you can use try-with-resources.
I'm trying to read ObjectOutputStream from a file and convert it to an arraylist.
This whole thing is happening inside a method which should read the file and return the array list:
public static List<Building> readFromDatabase(){
String fileName="database.txt";
FileInputStream fileIStream=null;
ObjectInputStream in=null;
List<Building> buildingsArr=null;
try
{
fileIStream = new FileInputStream(fileName);
in = new ObjectInputStream(fileIStream);
buildingsArr=(ArrayList<Building>)in.readObject();
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
Console.printPrompt("ArrayList<Building> class not found.");
e.printStackTrace();
}
finally{
Console.printPrompt("Closing file...");
close(in);
close(fileIStream);
return buildingsArr;
}
}
Java tells me that this is dangerous.
What are the alternatives?
I can't put the return in the "try" block because it won't do it / it won't close files in the "finally" block.
I need to both make sure files will be closed, and return the array list I created as well.
Any ideas?
I can't put the return in the "try" block because it won't do it / it
won't close files in the "finally" block.
Wrong, finally block would still execute if you put return in try block. Thus you can return in your try block.
try
{
//your code
return buildingsArr;
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
Console.printPrompt("ArrayList<Building> class not found.");
e.printStackTrace();
}
finally{
Console.printPrompt("Closing file...");
close(in);
close(fileIStream);
}
I would suggest starting to use Java 7, and the try with resources clause. http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Ex:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
You must either throw an Exception or return a value:
All you need to prove this is comment out the return "File Not Found" after the finally block and see that it won't compile.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ReturnFinallyExample
{
public static void main(final String[] args)
{
returnFinally();
}
private static String returnFinally()
{
try
{
final File f = new File("that_does_not_exist!");
final FileInputStream fis = new FileInputStream(f);
return "File Found!";
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
finally
{
System.out.println("finally!");
}
return "File Not Found!";
}
}
You must have the return after the finally or you have to either:
declare the method to throws FileNotFoundExceptoin and re-throw the FileNotException out.
or
wrap the FileNotFoundException with throw new RuntimeException(e)
I am wondering why I get this warning with the new eclipse Juno despite I think I correctly closed everything. Could you please tell me why I get this warning in the following piece of code?
public static boolean copyFile(String fileSource, String fileDestination)
{
try
{
// Create channel on the source (the line below generates a warning unassigned closeable value)
FileChannel srcChannel = new FileInputStream(fileSource).getChannel();
// Create channel on the destination (the line below generates a warning unassigned closeable value)
FileChannel dstChannel = new FileOutputStream(fileDestination).getChannel();
// Copy file contents from source to destination
dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
// Close the channels
srcChannel.close();
dstChannel.close();
return true;
}
catch (IOException e)
{
return false;
}
}
IF you're running on Java 7, you can use the new try-with-resources blocks like so, and your streams will be automatically closed:
public static boolean copyFile(String fileSource, String fileDestination)
{
try(
FileInputStream srcStream = new FileInputStream(fileSource);
FileOutputStream dstStream = new FileOutputStream(fileDestination) )
{
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
}
}
You won't need to explicitly close the underlying channels. However if you're not using Java 7, you should write the code in a cumbersome old way, with finally blocks:
public static boolean copyFile(String fileSource, String fileDestination)
{
FileInputStream srcStream=null;
FileOutputStream dstStream=null;
try {
srcStream = new FileInputStream(fileSource);
dstStream = new FileOutputStream(fileDestination)
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
} finally {
try { srcStream.close(); } catch (Exception e) {}
try { dstStream.close(); } catch (Exception e) {}
}
}
See how much better the Java 7 version is :)
You should always close in finally because if an exception rise, you won't close the resources.
FileChannel srcChannel = null
try {
srcChannel = xxx;
} finally {
if (srcChannel != null) {
srcChannel.close();
}
}
Note: even if you put a return in the catch block, the finally block will be done.
eclipse is warning you about the FileInputStream and FileOutputStream that you can no longer reference.
I am using a buffered writer and my code, closes the writer in the finally block. My code is like this.
...........
BufferedWriter theBufferedWriter = null;
try{
theBufferedWriter =.....
....
......
.....
} catch (IOException anException) {
....
} finally {
try {
theBufferedWriter.close();
} catch (IOException anException) {
anException.printStackTrace();
}
}
I have to use the try catch inside the clean up code in finally as theBufferedWriter might also throw an IOException. I do not want to throw this exception to the calling methos. Is it a good practice to use a try catch in finally? If not what is the alternative? Please suggest.
Regards,
Hiral
A somewhat nicer way to do this is to use IOUtils.closeQuiety from Apache commons-io. It keeps your code tidy and eliminates some of the boilerplate that's inherent in Java.
You code then becomes:
BufferedWriter theBufferedWriter = null;
try{
theBufferedWriter = ...
...
} catch (IOException anException) {
...
} finally {
IOUtils.closeQuietly(theBufferedWriter);
}
Much nicer and more expressive.
In pre Java 7, I'd say what you have written is the best solution.
In Java 7 and onwards you have Automatic Resource Management intended to simplify these things. With this feature, you can do
BufferedWriter theBufferedWriter = null;
try (BufferedWriter theBufferedWriter = ...) {
....
......
.....
} catch (IOException anException) {
....
}
Or you can use Lombok and the #Cleanup annotation and you shall never write a try catch inside finally again.
This is how you would normally write it (Note the throws IOException):
//Vanilly Java
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
}
Now with Lombok you just write #Cleanup on the streams
import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
#Cleanup InputStream in = new FileInputStream(args[0]);
#Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
This is what we will have to live with until Java 7 and ARM Blocks.
It's OK but you should test if theBufferedWriter is not null before closing it.
You could also do:
BufferedWriter theBufferedWriter;
try {
theBufferedWriter = new ...
try {
...
} finally {
try {
theBufferedWriter.close();
} catch (IOException closeException) {
closeException.printStackTrace();
}
}
} catch (IOException anException) {
...
}
or:
BufferedWriter theBufferedWriter;
try {
theBufferedWriter = new ...
} catch (IOException createException) {
// do something with createException
return; // assuming we are in a method returning void
}
try {
...
} catch (IOException anException) {
...
// assuming we don't return here
}
try {
theBufferedWriter.close();
} catch (IOException closeException) {
closeException.printStackTrace();
}
but mostly I do such operations (e.g. writing a file) in a dedicated method and prefer to throw the/an Exception so the caller can handle it (e.g. asking for another file, stopping the application, ...):
void someMethod(...) throws IOException {
BufferedWriter theBufferedWriter = new ...
try {
...
} catch (IOExcepption anException) {
try {
theBufferedWriter.close();
} catch (IOException closeException) {
closeException.printStackTrace();
// closeException is not thrown, anException represents the main/first problem
}
throw anException;
}
theBufferedWriter.close(); // throws the Exception, if any
}
Please note: English is not my first nor my second language, any help would be appreciated
It's ok to put a try-catch in a finally. It is the tool that does what you want to do. However, I feel the thrown IOException on close is uncommon enough that I would allow it to suppress any exception in the body like so.
try {
BufferedWriter writer = .....
try {
.....
} finally {
writer.close();
}
} catch (IOException e) {
....
}