使用字节流实现文件的切割以及文件的合并、文件的复制(三种)

2 篇文章 0 订阅
2 篇文章 0 订阅

实现文件分离(切割)

package com.IO;

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

/**
 * 实现文件分离【切割】
 * 实现文件合并器
 */
public class FileCutter02 {
    public static void main(String[] args) throws IOException {
        File file = new File("d:/music.flac");	// 需要分割的文件
        long size = 1024 * 1024 * 10;     // 表示每个文件体积最大为10M
        File dir = new File("d:/mus");		// 分割后每个子文件所在的文件夹
        // 将 f 对应的文件拆分成 N 份,每一份大小 至多 20MB,并将拆分后的文件依次序放入到dir 对应的目录中
        int split = split(file, size, dir);
        System.out.println(split);
    }

    /**
     * 该方法用于将指定文件 original 切割为体积不超过 size 字节的 N 份后, 依次序 放入到 directory 目录中。
     *
     * @param original  表示被拆分的原始文件
     * @param size      表示拆分后的文件的体积上限
     * @param directory 表示拆分后的文件的存储目录
     * @return 当 split 方法执行后,返回拆分后的文件数目。
     */
    public static int split(final File original, final long size, final File directory) throws IOException {
        // 参数校验
        if (original == null || !original.isFile()){
            throw new RuntimeException();
        }
        // 输出文件夹是否存在
        if (!directory.exists()){
            directory.mkdirs();
        }
        // 拆分文件的数量
        int count = 0;
        //  读取文件
        FileInputStream file = new FileInputStream(original);
        // 单文件大小一个数组能读取到范围
        if (size <= Integer.MAX_VALUE - 8){
            int s;
            byte[] bytes = new byte[(int) size];
            while ((s = file.read(bytes)) > 0) {
                File inFile = new File(directory + "/" + (count + 1) + ".temp");
                // 也可以使用下面这条语句,可用来解决合并后文件的损坏问题:
//                File inFile = new File(directory ,System.currentTimeMillis() + ".temp");
                OutputStream out = new FileOutputStream(inFile);
                out.write(bytes, 0, s);
                count++;
                out.close();
            }
        }else {
            // 一次读取不能完整读取一个文件  size > Integer.MAX_VALUE
            // 当前被分隔的文件是否以分隔完毕
            File outFile = new File(directory,count++ + ".temp");
            OutputStream outputStream = new FileOutputStream(outFile);
            long sum = size;
            while (size > Integer.MAX_VALUE - 8 && file.available() != 0){
                byte[] bytes = new byte[Integer.MAX_VALUE - 8];
                int readSize = file.read(bytes);
                outputStream.write(bytes,0, readSize);
                sum -= readSize;
            }
            // 没有满足单文件大小, 还有内容没读取
            if (file.available() != 0){
                byte[] bytes = new byte[(int) sum];
                int readSize = file.read(bytes);
                outputStream.write(bytes,0,readSize);

            }
            outputStream.close();
        }
        file.close();
        return count;
    }
}

实现文件合并

package com.IO;

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

/**
 * 实现文件合并器
 */
public class FileCutter02 {
    public static void main(String[] args) throws IOException {
        /**
         * 实现文件合并器
         */
        FileCombiner combiner = new FileCombiner();
        File file1 = new File("d:/mus");	// 需要合并的文件所在的文件夹
        File file2 = new File("d:/vedio-combined.flac");	// 合并后的文件
        long join = combiner.join(file1, file2);
        System.out.println(join);
    }
}
/**
 * 实现文件的合并
 */
class FileCombiner {
    /**
     * 该方法用于将指定目录 dir 中的多个文件片段依次序合并到同一个文件 target 中,并返回合并后的文件体积
     * 对应将大文件拆分后所得到的N个小文件的存放目录
     *
     * @param dir    表示文件片段所在的目录
     * @param target 参数 target 表示合并后的文件的存放路径名
     * @return 返回合并后的文件体积
     *
     * 合并文件被损坏,原因是:合并时子文件的顺序不对
     * 解决方案:
     *      1. 拆分时文件按照顺序命名(单线程下可用时间戳做文件名)
     *          例如:File inFile = new File(directory ,System.currentTimeMillis() + ".temp");
     *      2. 根据文件名自定义排序规则
     *          如下所示:
     */
    public long join(final File dir, final File target) throws IOException {
        // 参数校验
        if (dir == null || !dir.isDirectory()){
            throw new NullPointerException();
        }
        if (target == null){
            throw new NullPointerException();
        }
        if (!target.getParentFile().exists()){
            target.getParentFile().mkdirs();
        }
        long size = 0; // 声明用于统计合并后的文件体积的变量
        File[] files = dir.listFiles((file,name) -> name.endsWith(".temp"));
        if (files != null && files.length > 0){
            // 解决合并后文件损坏的第二种方案:自定义排序规则
            Arrays.sort(files,(f1,f2) -> {
                String n1 = f1.getName();
                String n2 = f2.getName();
                int index1 = Integer.parseInt(n1.split("\\.")[0]);
                int index2 = Integer.parseInt(n2.split("\\.")[0]);
                return index1 - index2;
            });

            // 创建文件输出流
            FileOutputStream outputStream = new FileOutputStream(target, true);
            for (File file : files) {
                if (file.length() <= Integer.MAX_VALUE - 8){
                    FileInputStream inputStream = new FileInputStream(file);

                    byte[] bytes = inputStream.readAllBytes();
                    outputStream.write(bytes);
                    inputStream.close();
                }else {
                    // 一次不能完全读取
                    FileInputStream inputStream = new FileInputStream(file);
                    while (inputStream.available() != 0){
                        byte[] bytes = new byte[Integer.MAX_VALUE - 8];
                        int readSize = inputStream.read(bytes);
                        outputStream.write(bytes,0,readSize);
                    }
                    inputStream.close();
                }
                size += file.length();
            }
            outputStream.close();
        }
        return size; // 返回合并后的文件体积
    }
}

文件复制

  • 第一种方法:通过byte 数组一个一个的写入到outputStream中
  • 第二种方法:通过readAllBytes 方法
  • 第三种方法:通过transferTo 方法
package com.IO;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 实现文件的复制功能
 * 第一种方法:通过byte 数组一个一个的写入到outputStream中
 * 第二种方法:通过readAllBytes 方法
 * 第三种方法:通过transferTo 方法
 */
public class BufferedOutputStreamDemo03 {
    public static void main(String[] args) {
        try {
            FileInputStream inputStream = new FileInputStream("d:/input-file.txt");
            FileOutputStream outputStream = new FileOutputStream("d:/kaifamiao/input-file.txt");

            // 第一种方法:通过byte 数组一个一个的写入到outputStream中
//            byte[] bytes = new byte[8193];
//            int size = 0;
//            if ((size = inputStream.read(bytes)) != -1){
//                outputStream.write(bytes,0, size);
//            }

            // 第二种方法:通过readAllBytes 方法
//            byte[] bytes1 = inputStream.readAllBytes();
//            outputStream.write(bytes1);

            // 第三种方法:通过transferTo 方法
            long l = inputStream.transferTo(outputStream);
            System.out.println(l);

            // 关闭流【只有关闭流后,内容才会被写入文件里面
            outputStream.close();
            inputStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-今非昔比°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值