Friday, June 12, 2009

Copy, move and delete files using Java

Delete
Deleting files in Java is fairly simple, just one method call-

   new File("file path").delete();

Only caveat here is that 'non-empty' directories can not be deleted. Of course you will need to have write permission (required for all write operations on file) on that directory as well.

Move
Moving files is also as simple as deleting, just one method call-

   new File("source file path").renameTo(new File("destination file path"));

Copy

Copying files in Java needs some heavy lifting as there is no API to do this task. Here is an example to copy files from one directory to another-

public void copyFiles(String source, String destination) throws IOException {
    File srcDir = new File(source);
    File[] files = srcDir.listFiles();

    FileChannel in = null;
    FileChannel out = null;
    for (File file : files) {
        try {
            in = new FileInputStream(file).getChannel();
            File outFile = new File(destination, file.getName());
            out = new FileOutputStream(outFile).getChannel();
            in.transferTo(0, in.size(), out);
        } finally {
            if (in != null)
                in.close();
            if (out != null)
                out.close();
        }
    }
}
The above example uses NIO API from Java 5, which finishes task pretty fast.

6 Comments:

David said...

One remark: renameTo does not work if your target path is on a different filesystem. It will simply return false.

Anonymous said...

Even though it's nice to have simple one liners for common IO operations, I would strongly suggest the use of Commons IO (http://commons.apache.org/io/) Apache project.

The methods and functionality provided in the Commons IO is implemented by experienced coders and they have all been tested in numerous large open source and commercial projects. This is particularly important since the Java IO facilities are subpart at best and useless at worst. Most methods return a boolean value for their result and they have many exceptional cases that need to be considered.

Hopefully the NIO2 changes that will be included in Java 7 will remedy the sorry state of file IO in the JVM.

Anonymous said...

Commons IO is a nice set of utilities but it appears to have it's own issues. After reading your comment I investigated using it on a project with some existing file utilities. Within 10 minutes I ran into two problems with the library. First, there is no way to iterate over lines in a file without reading them all into memory. Obviously this is not good when doing line-based processing of large files. Second, the file filters implement both the FileFilter and FilenameFilter interfaces. This requires a cast when using them with the File.listFiles() method. It's a minor issue, but it makes me curious about what other design warts I'll find as dig deeper. As always, caveat emptor.

Anonymous said...

To correct myself, I found the line iterator. On a somewhat different topic, it would be nice if these apache util libraries were updated to modern coding practices. Commons IO is very Java 1.4-ish. The lack of generics usage means lots of ugly casts in the code. I'll probably need to write a wrapper layer for some of the methods to keep the code clean and tight.

Anonymous said...

File.delete does not throw an exception when it fails, so making it very hard to know why the delete failed. With jdk7 (which has NIO2) then you can do f.toPath().delete() and it will throw an IOException with the reason why the delete failed.

For moving files when f.toPath().moveTo(...) can be used. The moveTo method has options to say if an existing file should be replaced or not or if you want the operation to be atomic.

For copying files there is f.toPath().copyTo(...). This knows how to copy file permissions and other meta data. It copies a single file or directory. To copy a directory tree you use it with Files.walkFileTree which knows how to handle symbolic links. There are simple examples in the javadoc, and more complete sample code in the samples directory.

I haven't used Commons IO but it may have some issues because it uses java.io.File.

Anonymous said...

The FileChannel.transferTo(..) may not copy all of the file bytes according to javadoc. You should then check the return value and repeat the call starting from the first non copied byte I think.