Sorin Adrian Carbunaru
Sorin Adrian Carbunaru

Reputation: 618

Why are only SOME of the files and folders not deleted?

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

Answers (5)

Teddy
Teddy

Reputation: 4233

You can check whether the Zip utility is closing the files properly... Do you have access to the ZipUsingJavaUtil class source?

  • Each entry in a zip file has to be closed.
  • Every file input stream opened for the zip writing process should be closed.

Check the below sample: http://www.journaldev.com/957/java-zip-example-to-zip-single-file-and-a-directory-recursively

Upvotes: 1

J-Dizzle
J-Dizzle

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

user3776663
user3776663

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

neo_lestat
neo_lestat

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

PandaConda
PandaConda

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

Related Questions