Fraser Price
Fraser Price

Reputation: 909

Not able to delete files in a given directory

I am trying to write a program which will delete all duplicate files in a directory. It is currently able to detect duplicates, but my deleting code does not seem to be working (Files.delete() returns false). Can anybody tell me why this is?

Current code:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.SecurityManager;

public class Duplicate {
    @SuppressWarnings("resource")
    public static boolean isDuplicate(File a, File b) throws IOException {
        FileInputStream as = new FileInputStream(a);
        FileInputStream bs = new FileInputStream(b);
        while(true) {
            int aBytes = as.read();
            int bBytes = bs.read();
            if(aBytes != bBytes) {
                return false;
            } else if(aBytes == -1) {
                System.out.println("Duplicate found: "+a.getName()+", "+b.getName());
                return true;
            }
        }
    }

    public static void main(String[] args) throws IOException {
        File dir = new File(System.getProperty("user.dir"));
        File[] files = dir.listFiles();
        for(int i = 0; i < files.length; i++) {
            for(int j = i+1; j < files.length; j++) {
                if(isDuplicate(files[i], files[j])) {
                    String filePath = System.getProperty("user.dir").replace("\\", "/")+"/"+files[i].getName();
                    System.out.println("Deleting "+filePath);
                    File f = new File(filePath);
                    if(f.delete())
                        System.out.println(filePath+" deleted successfully");
                    else
                        System.out.println("Could not delete "+filePath);
                }
            }
        }
    }
}

Upvotes: 1

Views: 68

Answers (2)

fge
fge

Reputation: 121720

Apart from the resources problem (which certainly explains why you can't delete), the problem is that you won't know why the deletion fails -- in fact, with File you have no means to know at all.

Here is the equivalent program written with java.nio.file, with resource management:

public final class Duplicates
{

    private Duplicates()
    {
        throw new Error("nice try!");
    }

    private static boolean duplicate(final Path path1, final Path path2)
        throws IOException
    {
        if (Files.isSameFile(path1, path2))
            return true;

        final BasicFileAttributeView view1
            = Files.getFileAttributeView(path1, BasicFileAttributeView.class);
        final BasicFileAttributeView view2
            = Files.getFileAttributeView(path2, BasicFileAttributeView.class);

        final long size1 = view1.readAttributes().size();
        final long size2 = view2.readAttributes().size();

        if (size1 != size2)
            return false;
        try (
            final FileChannel channel1 = FileChannel.open(path1,
                StandardOpenOption.READ);
            final FileChannel channel2 = FileChannel.open(path2,
                StandardOpenOption.READ);
        ) {
            final ByteBuffer buf1
                = channel1.map(FileChannel.MapMode.READ_ONLY, 0L, size1);
            final ByteBuffer buf2
                = channel2.map(FileChannel.MapMode.READ_ONLY, 0L, size1);

            // Yes, this works; see javadoc for ByteBuffer.equals()
            return buf1.equals(buf2);
        }
    }

    public static void main(final String... args)
        throws IOException
    {
        final Path dir = Paths.get(System.getProperty("user.dir"));
        final List<Path> list = new ArrayList<>();

        for (final Path entry: Files.newDirectoryStream(dir))
            if (Files.isRegularFile(entry))
                list.add(entry);

        final int size = list.size();

        for (int i = 0; i < size; i++)
            for (int j = i + 1; j < size; j++)
                try {
                    if (duplicate(list.get(i), list.get(j)))
                        Files.deleteIfExists(list.get(j));
                } catch (IOException e) {
                    System.out.printf("Aiie... Failed to delete %s\nCause:\n%s\n",
                        list.get(j), e);
                }
    }
}

Note: a better strategy would probably be to create a directory in which you will move all duplicates you detect; when done, just delete all files in this directory then the directory itself. See Files.move().

Upvotes: 3

Kapow36
Kapow36

Reputation: 76

Did you close your file streams? It would make sense that it would return false if the file is currently open.

Upvotes: 3

Related Questions