Combate Java: especifique o tamanho dos arquivos na pasta compactada

Trabalhem juntos para criar e crescer juntos! Este é o 22º dia da minha participação no "Nuggets Daily New Plan · August Update Challenge", clique para ver os detalhes do evento

I. Introdução

Hoje vou compartilhar com vocês um pequeno caso de um combate real escrito por mim mesmo.A principal função é especificar uma pasta, e depois agrupar e compactar os arquivos nela. Na verdade, este caso ainda tem alguns usos. Por exemplo, existem milhares de arquivos na pasta de log. Se eu precisar especificar 10M para cada pacote compactado e compactar os arquivos de log na pasta inteira, esse caso pode ser usado. . Não fale bobagem, vá direto para o código. O que eu uso aqui é o programa de console mais básico, principalmente porque a lógica do código tem certo significado de referência. Bem-vindo a trocar e aprender uns com os outros. Se houver algo errado, por favor me corrija!

Nota: Por enquanto, a situação em que há pastas na pasta não é considerada.

2. Exemplo de código

  1. Nova entidade FileModel.java

Especifique principalmente o nome do arquivo e o tamanho do arquivo, o que é conveniente para o agrupamento.

public class FileModel {
    public FileModel(String name, double fileSize) {
        this.name = name;
        this.fileSize = fileSize;
    }


    // 文件名
    public String name;
    // 文件大小KB
    public double fileSize;


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public double getFileSize() {
        return fileSize;
    }


    public void setFileSize(double fileSize) {
        this.fileSize = fileSize;
    }
}
复制代码
  1. Código Main.java:

O tamanho do agrupamento de arquivos em uma pasta é recursivo. Para conseguir o efeito o código é colocado em Main.java. O código específico tem comentários, basta olhar os comentários.

 private static final double FILE_SIZE=5500; // 指定分组压缩的大小 550KB
    private static final String PATH="D:\Test; // 指定要处理的文件夹
    public static void main(String[] args) {
        List<FileModel> list = getFiles(PATH);
        HashMap<Double, List<FileModel>> map = new HashMap<>();
        getArr(list,FILE_SIZE,map);
        if(map.size()>0)
        {
            for (Double aDouble : map.keySet()) {
                List<FileModel> fileModels = map.get(aDouble);
                batchZipFiles(fileModels,PATH+"\"+aDouble.toString()+".zip");
            }
        }
        System.out.println(map);
    }




    // 递归方式实现文件分组
    private static void getArr(List<FileModel> list, double fileSize,Map<Double, List<FileModel>> map) {
        List<FileModel> listAdd = new ArrayList<>();
        if (list.size() > 0) {
            for (FileModel fileModel : list) {
                if (listAdd.size() == 0) {
                    listAdd.add(fileModel);
                } else {


                    if (listAdd.stream().mapToDouble(FileModel::getFileSize).sum() < fileSize) {
                        listAdd.add(fileModel);
                        if(listAdd.size()==list.size())
                        {
                            map.put(listAdd.stream().mapToDouble(FileModel::getFileSize).sum(), listAdd);
                        }
                    } else {
                        // 取差集
                        list = list.stream().filter(item -> !listAdd.contains(item)).collect(Collectors.toList());
                        map.put(listAdd.stream().mapToDouble(FileModel::getFileSize).sum(), listAdd);
                        getArr(list,fileSize,map);
                        break;


                    }
                }
            }
        }


    }


    //读取文件夹获取里面文件的名字尺寸 不考虑嵌套文件夹
    private static List<FileModel> getFiles(String path) {
        List<FileModel> files = new ArrayList<FileModel>();
        File file = new File(path);
        File[] tempList = file.listFiles();
        if (tempList != null && tempList.length > 0) {
            for (File value : tempList) {
                if (value.isFile()) {
                    // System.out.println(value.getName() + ":" + getFileSizeString(value.length()));
                    files.add(new FileModel(
                            value.getName(), getFileSizeKB(value.length())
                    ));
                }
            }
        }
        return files;
    }


    // 获取文件大小KB
    private static double getFileSizeKB(Long size) {
        double length = Double.parseDouble(String.valueOf(size));
        return  length / 1024.0;


    }


    // 返回文件大小尺寸
    private static String getFileSizeString(Long size) {
        double length = Double.parseDouble(String.valueOf(size));
        //如果字节数少于1024,则直接以B为单位,否则先除于1024,后3位因太少无意义
        if (length < 1024) {
            return length + "B";
        } else {
            length = length / 1024.0;
        }
        //如果原字节数除于1024之后,少于1024,则可以直接以KB作为单位
        //因为还没有到达要使用另一个单位的时候
        //接下去以此类推
        if (length < 1024) {
            return Math.round(length * 100) / 100.0 + "KB";
        } else {
            length = length / 1024.0;
        }
        if (length < 1024) {
            //因为如果以MB为单位的话,要保留最后1位小数,
            //因此,把此数乘以100之后再取余
            return Math.round(length * 100) / 100.0 + "MB";
        } else {
            //否则如果要以GB为单位的,先除于1024再作同样的处理
            return Math.round(length / 1024 * 100) / 100.0 + "GB";
        }
    }


    /**
     *  压缩指定文件夹中的所有文件,生成指定名称的zip压缩包
     *
     * @param list 需要压缩的文件名称列表(包含相对路径)
     * @param zipOutPath 压缩后的文件名称
     **/
    public static void batchZipFiles(List<FileModel> list, String zipOutPath) {
        ZipOutputStream zipOutputStream = null;
        WritableByteChannel writableByteChannel = null;
        MappedByteBuffer mappedByteBuffer = null;
        try {
            zipOutputStream = new ZipOutputStream(new FileOutputStream(zipOutPath));
            writableByteChannel = Channels.newChannel(zipOutputStream);


            File file = new File(PATH);
            File[] tempList = file.listFiles();
            List<String> fileList = list.stream().map(FileModel::getName).collect(Collectors.toList());
            File[] addList=new File[fileList.size()];
            assert tempList != null;
            for (File file1 : tempList) {
                if(fileList.contains(file1.getName()))
                {
                    long fileSize = file1.length();
                    //利用putNextEntry来把文件写入
                    zipOutputStream.putNextEntry(new ZipEntry(file1.getName()));
                    long read = Integer.MAX_VALUE;
                    int count = (int) Math.ceil((double) fileSize / read);
                    long pre = 0;
                    //由于一次映射的文件大小不能超过2GB,所以分次映射
                    for (int i = 0; i < count; i++) {
                        if (fileSize - pre < Integer.MAX_VALUE) {
                            read = fileSize - pre;
                        }
                        mappedByteBuffer = new RandomAccessFile(file1, "r").getChannel()
                                .map(FileChannel.MapMode.READ_ONLY, pre, read);
                        writableByteChannel.write(mappedByteBuffer);
                        pre += read;
                    }
                }
            }
            assert mappedByteBuffer != null;
            mappedByteBuffer.clear();
        } catch (Exception e) {


        } finally {
            try {
                if (null != zipOutputStream) {
                    zipOutputStream.close();
                }
                if (null != writableByteChannel) {
                    writableByteChannel.close();
                }
                if (null != mappedByteBuffer) {
                    mappedByteBuffer.clear();
                }
            } catch (Exception e) {


            }
        }
    }
复制代码

3. Efeito de exibição

O efeito final da operação é o seguinte

Quarto, o último

Este caso implementa a função de especificar a compactação do tamanho do grupo. É apenas para referência e troca de aprendizado. Você pode me corrigir e propor um algoritmo melhor. Especialistas não pulverizam!

Endereço do código: gitee.com/hgm1989/fil…

おすすめ

転載: juejin.im/post/7132638265491849230