使用于NIO实现文件夹的复制/移动,删除

简介: 使用于NIO实现文件夹的复制/移动,删除

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;

public class NioFileUtil {
    
    private static final Logger logger=Logger.getLogger(NioFileUtil.class);
    
    /**
     * 复制文件夹
     * @param source
     * @param target
     * @param options
     * @throws IOException
     * @see {@link #operateDir(boolean, Path, Path, CopyOption...)}
     */
    public static void copyDir(Path source, Path target, CopyOption... options) throws IOException{
        operateDir(false, source, target, options);
    }
    /**
     * 移动文件夹
     * @param source
     * @param target
     * @param options
     * @throws IOException
     * @see {@link #operateDir(boolean, Path, Path, CopyOption...)}
     */
    public static void moveDir(Path source, Path target, CopyOption... options) throws IOException{
        operateDir(true, source, target, options);
    }
    /**
     * 复制/移动文件夹
     * @param move 操作标记,为true时移动文件夹,否则为复制
     * @param source 要复制/移动的源文件夹
     * @param target 源文件夹要复制/移动到的目标文件夹
     * @param options 文件复制选项 
     * @throws IOException
     * @see Files#move(Path, Path, CopyOption...)
     * @see Files#copy(Path, Path, CopyOption...)
     * @see Files#walkFileTree(Path, java.nio.file.FileVisitor)
     */
    public static void operateDir(final boolean move,final Path source, Path target, final CopyOption... options) throws IOException{
        if(null==source||!Files.isDirectory(source))
            throw new IllegalArgumentException("source must be directory");
        final Path dest = target.resolve(source.getFileName());
        // 如果相同则返回
        if(Files.exists(dest)&&Files.isSameFile(source, dest))return;
        // 目标文件夹不能是源文件夹的子文件夹
        // isSub方法实现参见另一篇博客 http://blog.csdn.net/10km/article/details/54425614
        if(isSub(source,dest))
            throw new IllegalArgumentException("dest must not  be sub directory of source");
        boolean clear=true;     
        for(CopyOption option:options)
            if(StandardCopyOption.REPLACE_EXISTING==option){
                clear=false;
                break;
            }
        // 如果指定了REPLACE_EXISTING选项则不清除目标文件夹
        if(clear)
            deleteIfExists(dest);
        Files.walkFileTree(source, 
                new SimpleFileVisitor() {

                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                        // 在目标文件夹中创建dir对应的子文件夹
                        Path subDir = 0==dir.compareTo(source)?dest:dest.resolve(dir.subpath(source.getNameCount(), dir.getNameCount()));
                        Files.createDirectories(subDir);
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        if(move)
                            Files.move(file, dest.resolve(file.subpath(source.getNameCount(), file.getNameCount())),options);
                        else
                            Files.copy(file, dest.resolve(file.subpath(source.getNameCount(), file.getNameCount())),options);
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                        // 移动操作时删除源文件夹
                        if(move)
                            Files.delete(dir);
                        return super.postVisitDirectory(dir, exc);
                    }
                });
    }

    /**
     * 强制删除文件/文件夹(含不为空的文件夹)

     * @param dir
     * @throws IOException
     * @see Files#deleteIfExists(Path)
     * @see Files#walkFileTree(Path, java.nio.file.FileVisitor)
     */
    public static void deleteIfExists(Path dir) throws IOException {
        try {
            Files.deleteIfExists(dir);
        } catch (DirectoryNotEmptyException e) {
            Files.walkFileTree(dir, new SimpleFileVisitor() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    return super.postVisitDirectory(dir, exc);
                }
            });
        }
    }

    /**
     * 判断sub是否与parent相等或在其之下

     * parent必须存在,且必须是directory,否则抛出{@link IllegalArgumentException}
     * @param parent 
     * @param sub
     * @return
     * @throws IOException 
     */
    public static boolean sameOrSub(Path parent,Path sub) throws IOException{
        if(null==parent)
            throw new NullPointerException("parent is null");
        if(!Files.exists(parent)||!Files.isDirectory(parent))
            throw new IllegalArgumentException(String.format("the parent not exist or not directory %s",parent));
        while(null!=sub) {
            if(Files.exists(sub)&&Files.isSameFile(parent, sub))
                return true;
            sub=sub.getParent();
        }
        return false;   
    }
    /**
     * 判断sub是否在parent之下的文件或子文件夹

     * parent必须存在,且必须是directory,否则抛出{@link IllegalArgumentException}
     * @param parent
     * @param sub
     * @return
     * @throws IOException
     * @see {@link #sameOrSub(Path, Path)}
     */
    public static boolean isSub(Path parent,Path sub) throws IOException{
        return (null==sub)?false:sameOrSub(parent,sub.getParent());
    }
    
    /**获取路径的完整地址
     * @param subPaths
     * @return
     * @throws Exception
     */
    public static String fileAbsolutePath(String...subPaths) throws Exception{
        if(null == subPaths || subPaths.length == 0){
            throw new Exception("路径不能为空");
        }
        
        StringBuffer buffer=new StringBuffer();
        
        for(int i=0;i<subPaths.length;i++){
            
            String subPath=subPaths[i];
            if(StringUtils.isEmpty(subPath)){
                continue;
            }
            if(i != 0){
                subPath=subPath.replaceFirst("^(?:\\|/)*", "");
            }
            subPath=subPath.replaceFirst("(?:\\|/)*$", "");
            buffer.append(subPath).append("/");
        }
        buffer.deleteCharAt(buffer.length()-1);
        
        String path=buffer.toString();
        
        String absolutePath=new File(path).getAbsolutePath();
        return absolutePath;
    }
    
    /**读取文件内容
     * @param path
     * @return
     * @throws Exception
     */
    public static String readFileContent(String path) throws Exception{
        File file=new File(path);
        if(!file.exists()){
            throw new Exception(StringUtil.format("文件 {} 不存在,无法获取内容",path));
        }else if(!file.isFile()){
            throw new Exception(StringUtil.format("文件 {} 不是文件,无法获取内容", path));
        }else if(!file.canRead()){
            throw new Exception(StringUtil.format("文件 {} 没有读取权限", path));
        }
        
        StringBuffer buffer=new StringBuffer();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"));
            String tempString = null;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                buffer.append(tempString);
                buffer.append("\n");
            }
        } catch (IOException e) {
            logger.error(StringUtil.format("文件 {} 读取内容失败,{}", path,e.getMessage()));
            throw e;
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        
        return buffer.toString();
    }
    
    /**读取文件内容写入输出流中
     * @param outputStream
     * @throws Exception
     */
    public static void readFileToOutputStream(String path,OutputStream outputStream) throws Exception{
        File file=new File(path);
        if(!file.exists()){
            throw new Exception(StringUtil.format("文件 {} 不存在,无法获取内容",path));
        }else if(!file.isFile()){
            throw new Exception(StringUtil.format("文件 {} 不是文件,无法获取内容", path));
        }else if(!file.canRead()){
            throw new Exception(StringUtil.format("文件 {} 没有读取权限", path));
        }
        
        byte[] b=new byte[1024];
        InputStream inputStream=null;
        int bCount=0;
        try{
            inputStream=new FileInputStream(file);
            
            while((bCount=inputStream.read(b))>0){
                outputStream.write(b, 0, bCount);
            }
            
        }catch(Exception e){
            logger.error(StringUtil.format("读取文件 {} 时出错,{}", path,e.getMessage()));
            throw e;
        }finally{
            if(null != inputStream){
                inputStream.close();
            }
        }
    }
    
    /**保存文件内容
     * @param path
     * @param fileContent
     * @param cover
     * @throws Exception
     */
    public static void saveFileContent(String path,String fileContent,boolean cover) throws Exception{
        File file=new File(path);
        if(!file.exists()){
            throw new Exception(StringUtil.format("文件 {} 不存在,无法获取内容",path));
        }else if(!file.isFile()){
            throw new Exception(StringUtil.format("文件 {} 不是文件,无法获取内容", path));
        }else if(!file.canRead()){
            throw new Exception(StringUtil.format("文件 {} 没有读取权限", path));
        }
        
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,!cover),"UTF-8"));
            
            writer.write(fileContent);
        } catch (IOException e) {
            logger.error(StringUtil.format("文件 {} 写入内容失败,{}", path,e.getMessage()));
            throw e;
        } finally {
            if (writer != null) {
                try {
                    writer.flush();
                    writer.close();
                } catch (IOException e1) {
                }
            }
        }
    }
    
    /**路径是否存在
     * @param path
     * @return
     * @throws Exception
     */
    public static boolean fileExists(String path,boolean dir) throws Exception{
        File file=new File(path);
        if(!file.exists()){
            return false;
        }
        if(dir){
            if(!file.isDirectory()){
                throw new Exception(StringUtil.format("路径 {} 不是文件夹", path));
            }
        }else{
            if(!file.isFile()){
                throw new Exception(StringUtil.format("路径 {} 不是文件", path));
            }
        }
        return true;
    }
    
}

相关文章
|
2月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
77 9
|
5月前
|
Java
java中实现File文件的重命名(renameTo)、将文件移动到其他目录下、文件的复制(copy)、目录和文件的组合(更加灵活方便)
这篇文章介绍了Java中使用`renameTo()`、`Files.copy()`等方法对文件进行重命名、移动和复制的操作,并提供了代码实例和测试效果。
java中实现File文件的重命名(renameTo)、将文件移动到其他目录下、文件的复制(copy)、目录和文件的组合(更加灵活方便)
|
7月前
|
安全 Java
Java文件操作:你真的会了吗?揭秘那些你不知道的读写、复制、删除技巧!
【6月更文挑战第27天】Java文件操作涵盖从基本读写到高效NIO技术。NIO的`Files`类用于高效读写大文件,如`readAllLines()`和`write()`方法。文件复制可借助`Files.copy()`,删除则用`deleteIfExists()`,减少异常处理。NIO通过缓冲区和通道减少I/O操作,提升性能。
30 0
|
8月前
|
Windows
FastCopy文件快速复制
FastCopy文件快速复制工具。Windows平台上最快的文件复制、删除软件!功能强劲,性能优越!它是源于日本的高效文件复制加速软件,支持拖拽操作,三种不同HDD模式;支持通配符,任务管理/命令行
51 0
|
8月前
|
Android开发
Android 关于文件及文件夹的创建 、删除、重命名、复制拷贝
Android 关于文件及文件夹的创建 、删除、重命名、复制拷贝
62 0
|
8月前
文件或目录的创建、删除、复制、移动
文件或目录的创建、删除、复制、移动
84 0
|
Java Apache
java复制文件的4种方式及拷贝文件到另一个目录下与删除单个文件和删除整个文件夹
java复制文件的4种方式及拷贝文件到另一个目录下与删除单个文件和删除整个文件夹
981 0
|
Java Apache
Java创建、重命名、删除文件和文件夹(转)
Java的文件操作太基础,缺乏很多实用工具,比如对目录的操作,支持就非常的差了。如果你经常用Java操作文件或文件夹,你会觉得反复编写这些代码是令人沮丧的问题,而且要大量用到递归。 下面是的一个解决方案,借助Apache Commons IO工具包(commons-io-1.1.jar)来简单实现文件(夹)的复制、移动、删除、获取大小等操作。
1699 0
|
Java
Java 把文件内容复制到另一个文件中
import java.io.*; public class FileCopy { public static void main(String[] args) throws IOException { BufferedWri...
1562 0