一、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
该包实现了上述两个接口