Reputation: 618
I am generating some files from my servlet (output.txt
) and from an XSL file (the folder generatedApps
and its content) and then pack the files and folders generated by the XSL transformation into a ZIP archive. After the client downloads the ZIP archive I want to delete it, as well as the other files and folders.
This is my code:
InputStream inputStream = new ByteArrayInputStream(request.getParameter("content")
.getBytes("UTF-8"));
try {
TransformerFactory tFactory = new net.sf.saxon.TransformerFactoryImpl();
Transformer transformer = tFactory.newTransformer(new StreamSource(
getServletContext().getResourceAsStream("lib/GenerateGeddyJsCode.xsl")));
FileOutputStream fos = new FileOutputStream("output.txt");
transformer.transform(new StreamSource(inputStream), new StreamResult(fos));
String appName = new Scanner(new File("output.txt")).useDelimiter("\\Z").next();
ZipUsingJavaUtil zipper = new ZipUsingJavaUtil();
zipper.zipFiles("generatedApps/" + appName, "generatedApps/" + appName + "Archive.zip");
String path = "generatedApps/";
String fileName = appName + "Archive.zip";
File f = new File(path + fileName);
response.setContentType("application/zip");
response.setContentLength((int)f.length());
response.addHeader("Content-Disposition","attachment;filename=\"" + fileName + "\"");
byte[] arBytes = new byte[32768];
FileInputStream is = new FileInputStream(f);
ServletOutputStream op = response.getOutputStream();
int count;
while ((count = is.read(arBytes)) > 0)
{
op.write(arBytes, 0, count);
}
op.flush();
op.close();
is.close();
fos.close();
inputStream.close();
File toBeDel = new File("generatedApps/");
GenerateGeddyJsCode.removeDirectory(toBeDel);
File output = new File("output.txt");
output.delete();
The method removeDirectory
is the following:
public static void removeDirectory(File dir) {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null && files.length > 0) {
for (File aFile : files) {
removeDirectory(aFile);
}
}
} else {
dir.delete();
}
}
The problem is that in the end only the ZIP archive is deleted (btw, the archive is inside generatedApps
). I tried to close all the streams, because I've read that not closed streams prevent deletion.
How can I also delete the remaining files and folders?
==================================== EDIT ========================================
My updated deletion method:
public static void removeDirectory(File dir) {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null && files.length > 0) {
for (File aFile : files) {
removeDirectory(aFile);
}
} else if (files.length == 0) {
dir.delete();
}
}
dir.delete();
}
Still not working.
==================================== EDIT 2======================================== Added:
InputStream inStream = getServletContext().getResourceAsStream("lib/GenerateGeddyJsCode.xsl");
StreamSource inStreamSource = new StreamSource(inStream);
Transformer transformer = tFactory.newTransformer(inStreamSource);
and later inStream.close()
. Still not working.
Upvotes: 2
Views: 245
Reputation: 4233
You can check whether the Zip utility is closing the files properly... Do you have access to the ZipUsingJavaUtil class source?
Check the below sample: http://www.journaldev.com/957/java-zip-example-to-zip-single-file-and-a-directory-recursively
Upvotes: 1
Reputation: 3191
If you're on linux you can do some command line versions of deleting files instead.
Runtime.getRuntime().exec("rm -rf");
'r' flag means recursion, meaning just start at the base and this command removes the directory and all subdirectories.
'f' flag forces it, doesn't ask you "do you want to delete xxxx.txt?" for every file.
you can also do something like
Runtime.getRuntime().exec("rm -rf *.java");
if you're only deleting Java files. Also, windows and mac have a shell delete file/ delete directory command. Hope this helps
Upvotes: 0
Reputation: 73
1) reformat your code ... can't see anything
2) close your streams within a finally block
try { ... } catch (Exception e) { ... handle your exception } finally { close what you have to close! }
3) " I tried to close all the streams, because I've read that not closed streams prevent deletion." Well, I guess you have still open file handles. Even foreign file handles can prevent the deletion. Is any anti virus program scanning the files? Search the internet for tools to detect open file handles.
4) You can also test if aFile.deleteOnExit() works. "deleteOnExit" tries to delete the file on JVM shutdown.
Good luck
Upvotes: 0
Reputation: 221
I want to post this in a comment but I don't have enough reputation. I tried your method to delete files and it is ok but if you can delete the "output.txt" file should be because there is an object using the file it seems that you close all the streams but checking the code I saw that you use a Scanner object to get the appName maybe that could be the problem because the Scanner object is pointing to your "output.txt" file.
Change this:
String appName = new Scanner(new File("output.txt")).useDelimiter("\\Z").next();
for something like this:
Scanner scanObject = new Scanner(new File("output.txt"));
String appName = scanObject.useDelimiter("\\Z").next();
scanObject.close();
I'm not sure about new Scanner(new File("output.txt")); I think the scanObject.close() should close also the File object that you are passing to the Scanner object if not, try to separate that also and close the File object after use the scanner.
Upvotes: 1
Reputation: 3506
You never remove the directory in your removeDirectory method.
You need to remove the else to have it execute unconditionally (for directories as well as non-directories).
public static void removeDirectory(File dir) {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null && files.length > 0) {
for (File aFile : files) {
removeDirectory(aFile);
}
}
}// else {
dir.delete();
// }
}
Upvotes: 1