Trying to make a simple ‘cut’ program to move files across folders. After it makes a copy it should delete the source file but it ignores the fileLocation.delete(); method in the try block. If I put it in the ‘finally’ block it works and also anywhere else in the program after it goes through copying the file but that makes no sense for it to work that way, even if something goes wrong the source will be deleted. My question is why does it ignore it, I was unable to find answers online. Thank you.
File fileLocation = new File("C:\fileLocation\picture.png"); File fileDestination = new File("C:\fileDestination\picture.png"); try(FileInputStream input = new FileInputStream(fileLocation); FileOutputStream output = new FileOutputStream(fileDestination)) { byte[] buffer = new byte[1024]; int length; while((length = input.read(buffer)) > 0) { output.write(buffer,0, length); } fileLocation.delete(); } catch(IOException exc) { System.out.println(exc.getMessage()); }
Advertisement
Answer
try(FileInputStream input = new FileInputStream(fileLocation); ... ) { // .. fileLocation.delete(); }
At this point, input
is still open, so you can’t delete the file it refers to.
According to the definition of try-with-resources in the language spec, a finally
block on a try-with-resources statement will be executed after the resource is closed. As such, putting the delete in the finally
block means it can succeed.
Rather than putting it in the finally
(which occurs whether or not an exception is thrown), you can split up the resources into two try-with-resources blocks, and delete once you’re done with input
:
try (FileOutputStream output = ...) { try (FileInputStream input = new FileInputStream(fileLocation)) { // .. } // input is now closed. fileLocation.delete(); } catch(IOException exc) { System.out.println(exc.getMessage()); }
Now, fileLocation
is only deleted when no IOException
is thrown from any preceding statement in the output
try-with-resources block (including the input
try-with-resources block).
Or, if you want not to delete it until output
is closed: move the IOException
catch into a surrounding try/catch (not try-with-resources) block:
try { try (FileOutputStream output = ...; FileInputStream input = ...) { // .. } // input and output are now both closed. fileLocation.delete(); } catch(IOException exc) { System.out.println(exc.getMessage()); }
Of course, a better way to move a file would be to use the utility method to move files, e.g.
Files.move(fileLocation.toPath(), fileDestination.toPath(), CopyOption.REPLACE_EXISTING);