Apache commons.io

Apache Commons IO 提供了一系列用于处理文件、目录、流、过滤和转换的工具方法。本文详细介绍了如何使用 `copyFileToDirectory`、`copyDirectoryToDirectory`、`deleteDirectory` 和 `moveDirectory` 等方法进行文件和目录的复制、删除及移动操作,包括对文件过滤和安全删除的处理。

一、Create、Modify

1、copyFileToDirectory

/**

     * Copies a file to a directory optionallypreserving the file date.

     * <p>

     * This method copies the contents of thespecified source file

 * toa file of the same name in the specified destination directory.

// destDir必须是文件夹,若不存在则会自动创建

     * The destination directory is created ifit does not exist.

     * If the destination file exists, thenthis method will overwrite it.

    */

    publicstaticvoidcopyFileToDirectory(final File srcFile, final File destDir, finalbooleanpreserveFileDate)

            throws IOException {

        if (destDir == null) {

            thrownew NullPointerException("Destination must not be null");

        }

        if (destDir.exists()&& destDir.isDirectory() == false) {

            thrownew IllegalArgumentException("Destination '" + destDir + "' is not a directory");

        }

        final File destFile = new File(destDir, srcFile.getName());

//java.io.File.File(File parent,String child)

        copyFile(srcFile, destFile, preserveFileDate);

//内部调用下面的copyFile方法

    }

 

/**

     * Copies a file to a new location.

     * <p>

     * This method copies the contents of thespecified source file

     * to the specified destination file.

     * The directory holding the destinationfile is created if it does not exist. // 目标文件父目录不存在则会创建

     * If the destination file exists, thenthis method will overwrite it.

     * // 目标文件存在则会覆盖

     */

    publicstaticvoid copyFile(final File srcFile, final File destFile,

                                finalbooleanpreserveFileDate) throws IOException {

        checkFileRequirements(srcFile, destFile);

        if (srcFile.isDirectory()) {

            thrownew IOException("Source'" + srcFile + "' exists but is a directory");

        }

        if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())){

            thrownew IOException("Source'" + srcFile + "' and destination '" + destFile + "' arethe same");

        }

        final File parentFile = destFile.getParentFile();

        if (parentFile != null) {

            if (!parentFile.mkdirs() && !parentFile.isDirectory()){

                thrownew IOException("Destination'" + parentFile + "' directory cannot be created");

            }

        }

        if (destFile.exists() && destFile.canWrite() == false) {

            thrownew IOException("Destination'" + destFile + "' exists but is read-only");

        }

        doCopyFile (srcFile, destFile, preserveFileDate);

// 内部调用doCopyFile方法实现

    }

}

 

/**

     * Internal copy file method.

     * This caches the original file length,and throws an IOException

     * if the output file length is differentfrom 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 istruncated part way

     * through copying the data and the newfile size is less than the current position.

     */

    privatestaticvoid doCopyFile(final File srcFile, final File destFile, finalbooleanpreserveFileDate)

            throws IOException {

        if (destFile.exists() && destFile.isDirectory()){

            thrownew IOException("Destination'" + destFile + "' exists but is a directory");

        }

 

        try (FileInputStream fis = new FileInputStream(srcFile);

             FileChannel input = fis.getChannel();

// 内部调用NIO channel

             FileOutputStream fos = new FileOutputStream(destFile);

             FileChannel output = fos.getChannel()) {

            finallongsize = input.size(); // TODO See IO-386

            longpos = 0;

            longcount = 0;

            while (pos < size) {

                finallongremain = size - pos;

                count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain;

                finallongbytesCopied = 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;

            }

        }

 

        finallongsrcLen = srcFile.length(); // TODO See IO-386

        finallongdstLen = destFile.length(); // TODO See IO-386

        if (srcLen != dstLen) {

            thrownew IOException("Failedto copy full contents from '" +

                    srcFile + "' to '" + destFile + "'Expected length: " + srcLen + " Actual: " + dstLen);

        }

        if (preserveFileDate) {

            destFile.setLastModified(srcFile.lastModified());

        }

    }

2、copyDirectoryToDirectory

/**

     * Copies a directory to within anotherdirectory preserving the file dates.

     * <p>

     * This method copies the source directoryand all its contents to a

     * directory of the same name in thespecified destination directory.

     * <p>

     * The destination directory is created if it does notexist.

     * If the destination directory did exist,then this method merges

     * the source with the destination, withthe source taking precedence.

      */

//默认不过滤文件

    publicstaticvoidcopyDirectoryToDirectory(final File srcDir, final File destDir) throws IOException {

        if (srcDir == null) {

            thrownew NullPointerException("Source must not be null");

        }

        if (srcDir.exists() && srcDir.isDirectory()== false) {

            thrownew IllegalArgumentException("Source '" + destDir + "' is not a directory");

        }

        if (destDir == null) {

            thrownew NullPointerException("Destination must not be null");

        }

        if (destDir.exists() && destDir.isDirectory()== false) {

            thrownew IllegalArgumentException("Destination '" + destDir + "' is not a directory");

        }

        copyDirectory(srcDir, new File(destDir, srcDir.getName()), true);

    }

 

/**

     * Copies a filtered directory to a newlocation.

     * <p>

     * This method copies the contents of thespecified source directory

     * to within the specified destinationdirectory.

     * <p>

     * The destination directory is created ifit does not exist.

     * If the destination directory did exist,then this method merges

     * the source with the destination, withthe source taking precedence.

     * <p>

     * <strong>Note:</strong> Setting <code>preserveFileDate</code> to

     * {@code true} tries to preserve thefiles' last modified

     * date/times using {@link File#setLastModified(long)}, however it is

     * not guaranteed that those operationswill succeed.

     * If the modification operation fails, noindication is provided.

     * </p>

     * <h3>Example: Copy directories only</h3>

     * <pre>

     * // only copy the directory structure

     * FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY,false);

     </pre>

     *

     * <h3>Example: Copy directories and txt files</h3>

     * <pre>

     * // Create a filter for ".txt" files

     * IOFileFilter txtSuffixFilter =FileFilterUtils.suffixFileFilter(".txt");

     * IOFileFilter txtFiles =FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);

     *

     * // Create a filter for either directories or ".txt" files

     * FileFilter filter =FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);

     *

     * // Copy using the filter

     * FileUtils.copyDirectory(srcDir, destDir, filter, false);

     </pre>

     **/

    publicstaticvoid copyDirectory(final File srcDir, final File destDir,

                                     final FileFilter filter, finalbooleanpreserveFileDate) throws IOException {

        checkFileRequirements(srcDir, destDir);

        if (!srcDir.isDirectory()) {

            thrownew IOException("Source'" + srcDir + "' exists but is not a directory");

        }

        if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())){

            thrownew IOException("Source'" + srcDir + "' and destination '" + destDir + "' arethe same");

        }

 

        // Cater for destination being directorywithin the source directory (see IO-141)

        List<String> exclusionList = null;

        if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath())) {

            final File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);  //文件如何过滤的

            if (srcFiles != null && srcFiles.length > 0) {

                exclusionList = new ArrayList<>(srcFiles.length);

                for (final File srcFile : srcFiles) {

                    final File copiedFile = new File(destDir, srcFile.getName());

                    exclusionList.add(copiedFile.getCanonicalPath());

                }

            }

        }

        doCopyDirectory(srcDir, destDir, filter, preserveFileDate, exclusionList);

    }

 

/**

     * Internal copy directory method

     */

    privatestaticvoid doCopyDirectory(final File srcDir, final File destDir, final FileFilter filter,

                                        finalbooleanpreserveFileDate, final List<String> exclusionList)

            throws IOException {

        // recurse

        final File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);

        if (srcFiles == null) { // null ifabstract pathname does not denote a directory, or if an I/O error occurs

            thrownew IOException("Failedto list contents of " + srcDir);

        }

        if (destDir.exists()) {

            if (destDir.isDirectory() == false) {

                thrownew IOException("Destination'" + destDir + "' exists but is not a directory");

            }

        } else {

            if (!destDir.mkdirs() && !destDir.isDirectory()){

                thrownew IOException("Destination'" + destDir + "' directory cannot be created");

            }

        }

        if (destDir.canWrite() == false) {

            thrownew IOException("Destination'" + destDir + "' cannot be written to");

        }

        for (final File srcFile : srcFiles) {

            final File dstFile = new File(destDir, srcFile.getName());

            if (exclusionList == null || !exclusionList.contains(srcFile.getCanonicalPath())) {

                if (srcFile.isDirectory()) {

                    doCopyDirectory(srcFile, dstFile, filter, preserveFileDate, exclusionList);  //文件夹则递归

                } else {

                    doCopyFile(srcFile, dstFile, preserveFileDate); //文件则copy

                }

            }

        }

 

        // Do this last, as the above has probablyaffected directory metadata

        if (preserveFileDate) {

            destDir.setLastModified(srcDir.lastModified());

        }

    }

3、copyToDirectory

内部调用copyFileToDirectory或者copyDirectoryToDirectory

即不需要判断src file是文件还是文件夹了

publicstaticvoid copyToDirectory(final File src, final File destDir) throws IOException {

        if (src == null) {

            thrownew NullPointerException("Source must not be null");

        }

        if (src.isFile()) {

            copyFileToDirectory(src, destDir);

        } elseif (src.isDirectory()) {

            copyDirectoryToDirectory (src, destDir);

        } else {

            thrownew IOException("Thesource " + src + " does not exist");

        }

    }

二、Delete

1、deleteDirectory

/**

     * Deletes a directory recursively.递归删除

       */

    publicstaticvoid deleteDirectory(final File directory) throws IOException {

        if (!directory.exists()) {

            return;

        }

 

        if (!isSymlink(directory)) {

            cleanDirectory(directory);

        }

 

        if (!directory.delete()) {

            final String message =

                    "Unable to delete directory " + directory + ".";

            thrownew IOException(message);

        }

    }

2、deleteQuietly

/**

     * Deletes a file, never throwing an exception. If file is a directory, delete it andall sub-directories.

     */

    publicstaticboolean deleteQuietly(final File file) {

        if (file == null) {

            returnfalse;

        }

        try {

            if (file.isDirectory()) {

                cleanDirectory(file);  //内部调用cleanDirectory,先清空文件夹

            }

        } catch (final Exception ignored) {

        }

 

        try {

            returnfile.delete();  //再去删除

        } catch (final Exception ignored) {

            returnfalse;

        }

    }

 

/**

     * Cleans a directory without deleting it.

把文件夹清空,但是不删除这个文件夹

        */

    publicstaticvoid cleanDirectory(final File directory) throws IOException {

        final File[] files = verifiedListFiles(directory);

 

        IOException exception = null;

        for (final File file : files) {

            try {

                forceDelete(file);

            } catch (final IOException ioe) {

                exception = ioe;

            }

        }

 

        if (null != exception) {

            throwexception;

        }

    }

/**

     * Lists files in a directory, assertingthat the supplied directory satisfies exists and is a directory

     */

    privatestatic File[] verifiedListFiles(final File directory) throws IOException {

        if (!directory.exists()) {

            final String message = directory + " doesnot exist";

            thrownew IllegalArgumentException(message);

        }

 

        if (!directory.isDirectory()) {

            final String message = directory + " is nota directory";

            thrownew IllegalArgumentException(message);

        }

 

        final File[] files = directory.listFiles();

        if (files == null) { // null ifsecurity restricted

            thrownew IOException("Failedto list contents of " + directory);

        }

        returnfiles;

    }

 

/**

     * Deletes a file. If file is a directory, deleteit and all sub-directories.

      */

    publicstaticvoid forceDelete(final File file) throws IOException {

        if (file.isDirectory()) {

            deleteDirectory(file);

        } else {

            finalbooleanfilePresent = file.exists();

            if (!file.delete()) {

                if (!filePresent) {

                    thrownew FileNotFoundException("File does not exist: " + file);

                }

                final String message =

                        "Unable to delete file:" + file;

                thrownew IOException(message);

            }

        }

    }

三、Move,rename

1、moveDirectory

目标目录必须存在,不然抛异常,不会自动创建,要自动创建的,可用moveDirectoryToDirectory

/**

     * Moves a directory.

     * <p>

     * When the destination directory is onanother file system, do a "copy and delete".

     */

    publicstaticvoid moveDirectory(final File srcDir, final File destDir) throws IOException {

        if (srcDir == null) {

            thrownew NullPointerException("Source must not be null");

        }

        if (destDir == null) {

            thrownew NullPointerException("Destination must not be null");

        }

        if (!srcDir.exists()) {

            thrownew FileNotFoundException("Source '" + srcDir + "' does not exist");

        }

        if (!srcDir.isDirectory()) {

            thrownew IOException("Source'" + srcDir + "' is not a directory");

        }

        if (destDir.exists()) {

            thrownew FileExistsException("Destination '" + destDir + "' already exists");

        }

先尝试rename,如果rename成功,说明是rename

        finalbooleanrename = srcDir.renameTo(destDir);

        if (!rename) {

            if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath() + File.separator)) {

                thrownew IOException("Cannotmove directory: " + srcDir + " to a subdirectory of itself: " + destDir);

            }

如果rename失败,也是土办法,赋值原来的到新地方,再删除原来的,

            copyDirectory(srcDir, destDir);

            deleteDirectory(srcDir);

            if (srcDir.exists()) {

                thrownew IOException("Failedto delete original directory '" + srcDir +

                        "' after copy to '" + destDir + "'");

            }

        }

}

 

2、moveFile(final FilesrcFile, final File destFile)

与上同理,也是先尝试rename,不行再copy删除

目标目录必须存在,不然抛异常,不会自动创建,要自动创建的,可用moveFileToDirectory

有更方便的,moveToDirectory,无需自己判断是移动文件还是文件夹

3、moveToDirectory

moveToDirectory (final File src, final File destDir,final boolean createDestDir)

 

 

四、文件过滤

1、java.io.FileFilter 

 

2、java.io.FilenameFilter

3、Apache Commons filefilter

该包实现了上述两个接口

使用 Apache Commons IO 将 `byte[]` 写入文件可以通过 `FileUtils` 类实现。`FileUtils` 提供了简洁的方法来简化文件操作,包括将字节数组直接写入文件的功能。具体操作如下: ```java import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; public class WriteByteArrayToFile { public static void main(String[] args) { // 示例byte数组 String data = "This is a test content."; byte[] byteArray = data.getBytes(); // 目标文件路径 File file = new File("output.txt"); try { // 使用FileUtils将byte数组写入文件 FileUtils.writeBytesToFile(file, byteArray); } catch (IOException e) { e.printStackTrace(); } } } ``` 在上述代码中,`FileUtils.writeBytesToFile()` 方法接受一个 `File` 对象和一个 `byte[]` 数组作为参数,并将字节数组内容写入指定的文件中。此方法简化了文件写入操作,避免了手动处理文件流的复杂性[^2]。 ### 注意事项 - **异常处理**:在进行文件操作时,必须捕获并处理 `IOException`,以应对文件无法创建、写入失败等异常情况。 - **依赖管理**:使用 Apache Commons IO 库之前,需要确保已正确导入 `commons-io.jar` 文件到项目中。可以通过 Maven 或手动添加 JAR 文件的方式完成依赖配置[^5]。 - **资源管理**:虽然 `FileUtils` 简化了文件操作,但在处理大文件时仍需注意性能优化。对于大文件写入,推荐使用缓冲流或分块写入策略[^4]。 通过 `FileUtils.writeBytesToFile()` 方法可以高效地将字节数组写入文件,适用于图像数据、文件上传下载等场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值