Copying a file using FileUtils.copyFile

2020-07-15 18:11发布

问题:

I am trying to copy files using file utils copy file method. I am running in to some issues where an exception is some times thrown

java.io.IOException: Failed to copy full contents from 'path.xml' to localfile.xml

I have googled and seen in the code that this exception is thrown when the target file length is different to the destination file length, The exception only occures some times - this could be due to the fact that the file i am trying to copy is consistantly updating so i might catch it mid update(just an xml file with values changing)

If i wrap the call in a if(target.canRead()) but this seems to make little difference.

Can anyone help?

*update:*I cannot lock the file as it is being written to via a third party vendor, this would cause all sorts of problems.

回答1:

I am not sure about how the architecture is implemented in your project, but you should have a locking mechanism on the file.

When some one is writing to the file it should lock it. And you should not be copying from it while its being written, ie it is locked.

FileInputStream in = new FileInputStream(file);
try {
    java.nio.channels.FileLock lock = in.getChannel().lock();
    try {
        Reader reader = new InputStreamReader(in, charset);
        ...
    } finally {
        lock.release();
    }
} finally {
    in.close();
}

See this question here on how to lock a file in java.

UPDATE

You are then left with no option but to implement copy method yourself or use a library that does not have a similar check.

You can see the code of FileUtils

It will give error if file changes during copy.

        if (srcFile.length() != destFile.length()) {
            throw new IOException("Failed to copy full contents from '" +
                    srcFile + "' to '" + destFile + "'");
        }


回答2:

I have the same problem (with large files) resolved using Files in Java 7 :

File srcFile = ...
File destFile = ...
File directory = ...
if (!Files.exists(directory.toPath())) {
    // use forceMkdir to create parent directory
    FileUtils.forceMkdir(directory);
}
Files.copy(srcFile.toPath(), new FileOutputStream(destFile));


回答3:

Well as you said the file might get updated during your copy process, so you should be required to get a file lock on the file you want to copy.

I suggest reading this question to get some detailed information of how to use a FileLock.