Java文件操作之复制、压缩、解压

Java文件操作之复制、压缩、解压

一、文件复制

1、通过文件流Stream对文件进行复制

这种方式的文件复制主要是通过InputStream读取文件流,再将读取的文件流数据写入到新创建的文件中。

/**
  * @Description 文件复制(使用Stream流操作)
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/24 15:15
  */
public static void copyFileByStream(File srcFile, File tarFile) {
    InputStream input = null;
    OutputStream output = null;
    try {
        input = new FileInputStream(srcFile);
        output = new FileOutputStream(tarFile);
        byte[] bytes = new byte[byteLen];
        //字节长度
        int byteLen = 0;
        while (true) {
            //字节为空时,跳出循环
            if (!((byteLen = input.read(bytes)) > 0)) {
                break;
            }
            //向目标文件写入流数据
            output.write(bytes, 0, byteLen);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    } finally {
        if (output != null) {
            IOUtils.closeQuietly(output);
        }
        if (input != null) {
            IOUtils.closeQuietly(input);
        }
    }
}

2、通过FileChannel对文件进行复制

FileChannel操作文件流时使用的是ByteBuffer缓存区,而InputStream/OutputStream文件操作使用的是byte[]数组,由于FileChannel使用的是ByteBuffer缓存区,所以性能上应该是优于InputStream/OutputStream的。

/**
  * @Description 使用FileChannel对文件进行复制,其实质还是通过
  *              FileInputStream和FileOutStream对文件流进行操作
  * @param srcFile
  * @param targetFile
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/24 14:43
  */
public static void copyFileByChannel(File srcFile, File targetFile) {
    FileChannel inputFileChannel = null;
    FileChannel outputFileChannel = null;
    try {
        inputFileChannel = new FileInputStream(srcFile).getChannel();
        outputFileChannel = new FileOutputStream(targetFile).getChannel();
        outputFileChannel.transferFrom(inputFileChannel, 0, inputFileChannel.size());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    } finally {
        if (outputFileChannel != null) {
            IOUtils.closeQuietly(outputFileChannel);
        }
        if (inputFileChannel != null) {
            IOUtils.closeQuietly(inputFileChannel);
        }
    }
}

3、通过commons-io工具包提供的copy方法拷贝

使用方法如下:

  • 引入jar包
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.2</version>
</dependency>
  • 调用方法
FileUtils.copyFile(srcFile, targetFile);
  • copy方法的源码
/**
 * Internal copy file method.
 * 
 * @param srcFile  the validated source file, must not be <code>null</code>
 * @param destFile  the validated destination file, must not be <code>null</code>
 * @param preserveFileDate  whether to preserve the file date
 * @throws IOException if an error occurs
 */
private static void doCopyFile(File srcFile, File destFile, 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);
        input  = fis.getChannel();
        output = fos.getChannel();
        long size = input.size();
        long pos = 0;
        long count = 0;
        while (pos < size) {
            count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos;
            pos += output.transferFrom(input, pos, count);
        }
    } finally {
        IOUtils.closeQuietly(output);
        IOUtils.closeQuietly(fos);
        IOUtils.closeQuietly(input);
        IOUtils.closeQuietly(fis);
    }

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

由以上源码可以看出FileUtils.copy(srcFile, targetFile)实际上使用的是FileChannel的方式进行文件拷贝。

二、文件压缩

文件压缩的方法有两种情况:

  • 压缩的对象是文件夹
  • 压缩的对象是文件
  1. 压缩对象是文件时,不需要考虑是否存在子项
 /**
  * @Description 压缩文件,将文件压缩在源文件所在的目录下
  * @param srcFilePath 要压缩的文件
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/11 15:16
  */
public static void zipFile(String srcFilePath) {
    File srcFile = new File(srcFilePath);
    if (!srcFile.exists()){
        return;
    }

    FileOutputStream fos = null;
    ZipOutputStream zos = null;
    //获取到文件路径
    String zipFilePath = srcFile.getPath();
    //压缩文件的路径
    String destFilePath = zipFilePath.substring(0, zipFilePath.indexOf(".") + 1) + "zip";
    File dstFile = new File(destFilePath);
    try {
        //输出的文件
        fos = new FileOutputStream(dstFile);
        CheckedOutputStream cos = new CheckedOutputStream(fos, new CRC32());
        zos = new ZipOutputStream(cos);
        //数据写入
        writeDataToZip(srcFile, zos, "");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (zos != null) {
            IOUtils.closeQuietly(zos);
        }
        if (fos != null) {
            IOUtils.closeQuietly(fos);
        }
    }
}

/**
  * @Description 数据写入压缩文件
  * @param srcFile
  * @param zos
  * @param baseDir
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/28 17:18
  */
private static void writeDataToZip(File srcFile, ZipOutputStream  zos, String baseDir) {
    BufferedInputStream bis = null;
    try {
        //源文件流
        bis = new BufferedInputStream(new FileInputStream(srcFile));
        //创建压缩文件实体
        String name = baseDir + srcFile.getName();
        ZipEntry entry = new ZipEntry(name);
        zos.putNextEntry(entry);
        int count;
        byte data[] = new byte[byteLen];
        //写入数据
        while ((count = bis.read(data, 0, byteLen)) != -1) {
            zos.write(data, 0, count);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (bis != null) {
            IOUtils.closeQuietly(bis);
        }
    }
}

2. 压缩对象是文件夹时,需要考虑文件夹层级和文件夹下的文件项

 /**
  * @Description 压缩一个文件夹下的所有文件
  * @param srcFilePath 
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/24 15:59
  */
public static void zipFilePath(String srcFilePath) {
    System.out.println(srcFilePath);
    File srcFile = new File(srcFilePath);
    if (!srcFile.exists()) {
        System.out.println("文件路径错误!");
        return;
    }
    FileOutputStream fos = null;
    ZipOutputStream zos = null;
    //获取到文件路径
    String zipFilePath = srcFile.getPath();
    //压缩文件的路径
    String destFilePath = srcFile.getParent() +"\\"+ zipFilePath.substring(zipFilePath.lastIndexOf("\\") + 1) + ".zip";
    File dstFile = new File(destFilePath);
    try {
        fos = new FileOutputStream(dstFile);
        CheckedOutputStream cos = new CheckedOutputStream(fos,new CRC32());
        zos = new ZipOutputStream(cos);
        File[] files = srcFile.listFiles();
        //遍历文件压缩
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {
                zipDirectory(files[i], zos, files[i].getName() + "/");
            } else {
                writeDataToZip(files[i], zos, "");
            }
        }
    }  catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (zos != null) {
            IOUtils.closeQuietly(zos);
        }
        if (fos != null) {
            IOUtils.closeQuietly(fos);
        }
    }
}

/**
  * @Description 遍历文件夹下的文件
  * @param directoryFile
  * @param zos
  * @param baseDir
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/28 18:05
  */
private static void zipDirectory(File directoryFile, ZipOutputStream zos, String baseDir) {
    File[] files = directoryFile.listFiles();
    for (int i = 0; i < files.length; i++) {
        if (files[i].isDirectory()) {
            zipDirectory(files[i], zos, baseDir + files[i].getName() + "/");
        } else {
            if (files[i].exists()) {
                writeDataToZip(files[i], zos, baseDir);
            }
        }
    }
}

三、文件解压

将需要解压的.zip文件解压到目标文件夹下。

 /**
  * @Description 解压文件
  * @param zipFile  需要解压的文件
  * @param unZipPath 文件解压后存放的路径
  * @Return void
  * @Author Mr.Walloce
  * @Date 2019/8/25 15:17
  */
public static void unZipFile(File zipFile, String unZipPath) {
    File pathFile = new File(unZipPath);
    if(!pathFile.exists()){
        pathFile.mkdirs();
    }
    ZipFile zip = null;
    InputStream is = null;
    OutputStream os = null;
    try {
        zip = new ZipFile(zipFile);
        //遍历解压文件
        for(Enumeration entries = zip.entries();entries.hasMoreElements();){
            ZipEntry entry = (ZipEntry)entries.nextElement();
            String zipEntryName = entry.getName();
            is =  zip.getInputStream(entry);
            String outPath = (unZipPath+"/"+zipEntryName).replaceAll("\\*", "/");;
            //判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            if(!file.exists()){
                file.mkdirs();
            }
            //判断文件全路径是否为文件夹
            if(new File(outPath).isDirectory()){
                continue;
            }
            //解压后输出文件
            os = new FileOutputStream(outPath);
            byte[] buf1 = new byte[byteLen];
            int len;
            while((len = is.read(buf1)) > 0){
                os.write(buf1,0,len);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (is != null) {
            IOUtils.closeQuietly(is);
        }
        if (os != null) {
            IOUtils.closeQuietly(os);
        }
    }
}


以上是我整理的一些对文件操作工具,仅供学习参考,如有错误希望能指出,大家共同学习进步!

猜你喜欢

转载自www.cnblogs.com/yin1361866686/p/11426902.html
今日推荐