java : FileChannel 复制文件

237 阅读1分钟

copy文件,channel(管道)主打的就是一个快

/**
 * Internal copy file method.
 * This caches the original file length, and throws an IOException
 * if the output file length is different from the current input file length.
 * So it may fail if the file changes size.
 * It may also fail with "IllegalArgumentException: Negative size" if the input file is truncated part way
 * through copying the data and the new file size is less than the current position.
 *
 * @param srcFile          the validated source file, must not be {@code null}
 * @param destFile         the validated destination file, must not be {@code null}
 * @param preserveFileDate whether to preserve the file date
 * @throws IOException              if an error occurs
 * @throws IOException              if the output file length is not the same as the input file length after the
 * copy completes
 * @throws IllegalArgumentException "Negative size" if the file is truncated so that the size is less than the
 * position
 */
private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate)
        throws IOException {
    if (destFile.exists() && destFile.isDirectory()) {
        throw new IOException("Destination '" + destFile + "' exists but is a directory");
    }

    FileInputStream fis = null;
    FileOutputStream fos = null;
    FileChannel input = null;
    FileChannel output = null;
    try {
        fis = new FileInputStream(srcFile);
        fos = new FileOutputStream(destFile);
        // 在 Channel 上操作
        input = fis.getChannel();
        output = fos.getChannel();
        final long size = input.size(); // TODO See IO-386
        long pos = 0;
        long count = 0;
        while (pos < size) {
            final long remain = size - pos;
            count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain;
            // transferFrom : 开始交换: input -->output
            final long bytesCopied = output.transferFrom(input, pos, count);
            if (bytesCopied == 0) { // IO-385 - can happen if file is truncated after caching the size
                break; // ensure we don't loop forever
            }
            pos += bytesCopied;
        }
    } finally {
        CloseableUtils.closeQuietly(output, fos, input, fis);
    }

    final long srcLen = srcFile.length(); // TODO See IO-386
    final long dstLen = destFile.length(); // TODO See IO-386
    if (srcLen != dstLen) {
        throw new IOException("Failed to copy full contents from '" +
                srcFile + "' to '" + destFile + "' Expected length: " + srcLen + " Actual: " + dstLen);
    }
    if (preserveFileDate) {
        destFile.setLastModified(srcFile.lastModified());
    }
}