0

There's something going on here that I don't understand. This code deletes all the files in the "stuff"directory:

public static void main(String[] args) throws Exception {

    File dire = new File("C:\\Users\\spacitron\\Desktop\\Stuff");

    for (File doc : dire.listFiles()) {
        doc.delete();
    }

}

However it won't work if I try to do something useful with it, such as only deleting duplicate files:

public static void main(String[] args) throws Exception {

    File dire = new File("C:\\Users\\spacitron\\Desktop\\Stuff");
    ArrayList<String> hashes = new ArrayList<>();
    for (File doc : dire.listFiles()) {
        String docHash = getHash(doc);
        if (hashes.contains(docHash)) {
            doc.delete();
        } else {
            hashes.add(docHash);
        }
    }

}

public static String getHash(File d) {
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA1");
        FileInputStream inStream = new FileInputStream(d);
        DigestInputStream dis = new DigestInputStream(inStream, md);
        BufferedInputStream bis = new BufferedInputStream(dis);
        while (true) {
            int b = bis.read();
            if (b == -1)
                break;
        }
    } catch (NoSuchAlgorithmException | IOException e) {
        e.printStackTrace();
    }

    BigInteger bi = new BigInteger(md.digest());

    return bi.toString(16);
}

What gives?

spacitron
  • 2,095
  • 7
  • 30
  • 39
  • try closing the streams? – Farlan Jun 24 '13 at 12:55
  • 1
    you are not closing hte input streasms – Arun P Johny Jun 24 '13 at 12:55
  • 1
    equal hashes != equal files but !equal Hashes == !equal files .... just because the hases are the same... doesn't mean its the same file. but if the hash is different.. the files are different – Philipp Sander Jun 24 '13 at 12:56
  • @PhilippSander SHA-1 does not have any chance collisions. See [this answer](http://stackoverflow.com/questions/800685/which-cryptographic-hash-function-should-i-choose/817121#817121). – ntoskrnl Jun 24 '13 at 13:16
  • @spacitron Note that bi.toString(16) may not return what you expect. It omits leading zeros. It doesn't matter in this case, but to avoid surprises, you should either pad it, or use a proper byte array to hex converter, such as BaseEncoding from [Guava](http://code.google.com/p/guava-libraries/) or Hex from [Commons Codec](http://commons.apache.org/proper/commons-codec/). – ntoskrnl Jun 24 '13 at 13:22

2 Answers2

2

You need to close your input streams in a finally block would be best, These will be accessing you files still preventing them from being deleted as they are in use

    FileInputStream inStream = null;
    DigestInputStream dis = null;
    BufferedInputStream bis = null;

    try {
       md = MessageDigest.getInstance("SHA1");
       inStream = new FileInputStream(d);
       dis = new DigestInputStream(inStream, md);
       bis = new BufferedInputStream(dis);
       while (true) {
            int b = bis.read();
            if (b == -1)
                break;
            }
   } catch (NoSuchAlgorithmException | IOException e) {
       e.printStackTrace();
   } finally {
       try{
          if(inStream!= null)
              inStream.close();
          if(dis != null)
              dis.close();
          if(bis != null)
              bis.close()
      } catch (Exception ex){
          ex.printStackTrace()
      }         
    }
Java Devil
  • 10,629
  • 7
  • 33
  • 48
  • You should probably use try-with-resources if you have access to Java 7 (which you do seem to have as you're using multi-catch), as that cleans up a lot of boilerplate cruft. The code posted in this answer may fail to close some of the streams if one of the calls to close() throws an exception. – ntoskrnl Jun 24 '13 at 13:07
2

Windows does not permit deleting files that are open, unless they are opened with a special flag that is unavailable when programming in Java. While this code would work on a Unix system, on Windows it won't.

Closing open files is a good idea in general because operating systems impose a limit on the number of files that an application can have open at any given time.

Joni
  • 108,737
  • 14
  • 143
  • 193