This week's book giveaway is in the Kotlin forum.
We're giving away four copies of Kotlin in Action and have Dmitry Jemerov & Svetlana Isakova on-line!
See this thread for details.
Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Deleting file after method throws exception  RSS feed

 
Chad Schultz
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How do I delete a file after I've passed it to a method that ends abnormally?

I'm trying to write an integration test for a simple program by extending Spring's AbstractDependencyInjectionSpringContextTests and using JUnit.

In one test, I create a tempfile, then call a method which is supposed to contact a remote service (via Spring and HTTPInvoker), retrieve data, and write it to the file. Then the method must delete the file.

However, this test specifically is to ensure the program properly handles the error when the service cannot be contacted (I'm using a bad URL to simulate this). So:
1. the file is created
2. the method is called
3. the method attempts to contact the remote service
4. the remote service call fails
5. the method throws a RuntimeException
6. the test catches the exception
7. the test tries to delete the file

However, delete() returns false, and the file is still there. deleteOnExit() doesn't work, either. If I comment out the method call, the file is deleted. My theory is that the machine believes the file to be open and in use by the method, and so won't allow it to be deleted. How do I have the code clean up its own mess and remove the files it creates each time I run the test? Thanks!
 
Kaydell Leavitt
Ranch Hand
Posts: 690
Eclipse IDE Firefox Browser Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Would it work to call the close() method of File before calling delete()? (Perhaps surrounded in a try-catch?

Kaydell
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's a good chance that something needs to be closed, yes. Not a File object, because File doesn't have a close() method. But a FileOutputStream, FileWriter, RandomAccessFile, or other similar classes (for input or output) - those do need to be closed. And it's recommended if at all possible to use a finally block, not just a catch block. Whether an error occurred or not, when you're done with a file and the class associated with it goes out of scope, make sure it's closed. If not... well garbage collection may well take care of it eventually, but it's unreliable. Sometimes it will take too long, and leave you with this sort of situation.

Unfortunately there are also some times when even though you've dutifully closed everything like you should, the system may be a little slow in recognizing that. I maintain that the close() method shouldn't return until the file resources are really closed. But apparently, that's not always the case on some systems. In this case, if the file is being written by some sort of remote process, there may be some sort of networking lag between when the remote process thoguht the file was closed, and, and when the local filesystem thought it was. In this case, you may need to insert a delay and retry. Maybe write a loop that keeps retrying every 100 milliseconds until 10 seconds expire, then gives up. Or whatever times you think are appropriate. To test the idea, just insert a single 10-second delay before the delete, and see if it fixes the problem. If it does, then you can write a more careful loop to control the retry strategy.
 
Chad Schultz
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Kaydell, you reminded me of the fact that I'm using a FileWriter as well. I think that's where the problem is. I had a try block with a sequence of method calls, each relying on the last, each throwing a different exception. I created the FileWriter partway through and closed it at the end- but of course, if it hit an exception, it wouldn't reach that.

After quite a bit of frustrated experimentation, I discovered the only way to make this work and avoid "variable may not have been initialized" compiler errors (yes, Eclipse treats it as an error and so will not compile the file, even if @SupressWarnings is used), I initialized the FileWriter to null before the try block, then added a "finally" block with an IOException try/block inside that (never mind that the big try block already had one!) and THERE I was able to close the FileWriter. It doesn't look pretty, but it works.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!