JAVA实现文件拆分与合并

文件拆分(切割)

将大文件拆分成多个小文件,每个小文件的大小可以自定义,这样可以方便传输,也可以方便存储。 步骤:

  1. 创建一个文件输入流对象,关联数据源文件

  2. 创建一个文件输出流对象,关联子文件

    • 为了防止子文件覆盖,需要在文件名后面加上编号

    • 会有多个子文件,所以需要使用循环

  3. 读取数据源文件,将读取到的字节写入到子文件

  4. 关闭资源

文件合并

将多个小文件合并成一个大文件,这样可以方便存储,也可以方便传输。 步骤:

  1. 创建一个文件输出流对象,关联目的地文件

  2. 创建一个文件输入流对象,关联数据源文件

    • 会有多个子文件,所以需要使用循环

  3. 读取数据源文件,将读取到的字节写入到目的地文件

  4. 关闭资源

代码 


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Test01 {

    public static void main(String[] args) {
        File file = new File("d:/temp/jianghu.mp4"); //原文件
        long size = 1024 * 1024; //指定拆分后每个文件的大小
        File dir = new File("d:/temp/day01", "cutter"); //拆分后文件地址
        int count = split(file, size, dir); //计算拆分后文件数量
        System.out.println(count);
    }

    public static int split(final File original, final long size, final File directory) {
        // 参数校验
        if (original == null || !original.isFile()) {
            return 0;
        }

        // 输出文件夹是否存在
        if (!directory.exists()) {
            directory.mkdirs();
        }

        int count = 0; // 拆分文件的数量
        try (FileInputStream fis = new FileInputStream(original)) {
            // 单文件大小一个数组能读取到范围
            if (size <= Integer.MAX_VALUE - 8) {
                //最大数组大小定义为Integer.MAX_VALUE - 8,作为自己需要8 bytes存储大小
                byte[] bytes = new byte[(int) size];
                int readSize;   // readSize 读取的字节数
                while (fis.available() != 0) {//可读取字节数
                    readSize = fis.read(bytes);
                    File outFile = new File(directory, count++ + ".kfm");
                    // 用输出流创建子文件
                    FileOutputStream fos = new FileOutputStream(outFile);

                    fos.write(bytes, 0, readSize);//这么做防止写入重复的字节

                    System.out.println("分隔文件:" + outFile);
                    fos.close();
                }

            } else {
                // 一次读取不能完整读取一个文件  size > Integer.MAX_VALUE
                // 当前被分隔的文件是否以分隔完毕
                while (fis.available() != 0) { // 每循环一个会创建一个子文件
                    // 用输出流创建子文件
                    File outFile = new File(directory, count++ + ".part");
                    FileOutputStream fos = new FileOutputStream(outFile);

                    long sum = size; // 单文件大小

                    while (sum > Integer.MAX_VALUE - 8 && fis.available() != 0) {
                        byte[] bytes = new byte[Integer.MAX_VALUE - 8];
                        int readSize = fis.read(bytes);
                        fos.write(bytes, 0, readSize);
                        sum -= readSize;
                    }
                    // 没有满足单文件大小, 还有内容没读取
                    if (fis.available() != 0) {
                        byte[] bytes = new byte[(int) sum];
                        int readSize = fis.read(bytes);
                        fos.write(bytes, 0, readSize);
                    }
                    fos.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }
}
package com.ketan.lianxi26;

import java.io.*;
import java.util.Arrays;

public class Test02 {

    public static void main(String[] args) {
        //拆分后文件地址
        File dir = new File("d:/temp/day01/cutter");
        //合并后文件存放地址
        File file = new File("d:/temp/合并后的视频.mp4");

        long size = join(dir, file);
        System.out.println(size);

//        String path = "d:/io/cutter/10.kfm";
//        String path1 = "d:/io/cutter/2.kfm";
//
//        System.out.println(path.compareTo(path1));
    }

    /**
     * 将指定目录中的多个文件片段依次序合并到同一个文件中,并返回合并后的文件体积
     *
     * @param dir    存放文件片段的目录(即拆分文件后的N个小文件的存放目录)
     * @param target 表示合并后的文件的存放路径
     * @return 返回合并后的文件体积
     * 

* 合并后文件被损坏,原因:合并时子文件的顺序不对 * 解决方案: * 1. 拆分时文件名按照顺序命名(单线程下可用时间戳做文件名) * 2. 根据文件名自定义排序规则 */ public static long join(final File dir, final File target) { long size = 0; // 声明用于统计合并后的文件体积的变量 // 参数校验 if (dir == null || !dir.isDirectory()) { return size; } // 参数校验 if (target == null) { return size; } if (!target.getParentFile().exists()) { target.getParentFile().mkdirs(); } // 合并文件 File[] files = dir.listFiles((file, name) -> name.endsWith(".kfm")); if (files != null && files.length > 0) { // 判断是否有文件片段 // 保证顺序 Arrays.sort(files, (f1, f2) -> { String name1 = f1.getName(); String name2 = f2.getName(); int index1 = Integer.parseInt(name1.split("\\.")[0]); int index2 = Integer.parseInt(name2.split("\\.")[0]); return index1 - index2; }); try { FileOutputStream fos = new FileOutputStream(target); // 创建文件输出流 for (File file : files) { // 遍历文件片段 if (file.length() <= Integer.MAX_VALUE - 8) { // 一次可以完全读取 FileInputStream fileInputStream = new FileInputStream(file); byte[] bytes = fileInputStream.readAllBytes(); fos.write(bytes); fileInputStream.close(); } else { // 一次不能完全读取 FileInputStream fileInputStream = new FileInputStream(file); while (fileInputStream.available() != 0) { byte[] bytes = new byte[Integer.MAX_VALUE - 8]; int readSize = fileInputStream.read(bytes); fos.write(bytes, 0, readSize); } fileInputStream.close(); } size += file.length(); } fos.close(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } return size; // 返回合并后的文件体积 } }

你可能感兴趣的:(java,python,开发语言)