首页 > 其他分享 >大文件去重

大文件去重

时间:2024-09-24 23:01:35浏览次数:10  
标签:文件 splitSize PrintWriter File tempString new

若文件存的字符如下图,要求进行去重

可将数据存入HashSet,如下,但如果文件很大,大于虚拟机内存的话,会报异常java.lang.OutOfMemoryError: Java heap space

        HashSet set = new HashSet();
        File file = new File("E:\\aa.txt");
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String tempString = null;
        while ((tempString = reader.readLine()) != null) {
            tempString = tempString.trim();
            if(tempString != ""){
                System.out.println(tempString);
                set.add(tempString);
            }
        }

可尝试用分批读取,用Hash取模方法将大文件拆分成若干小文件,再将若干个小文件的数据存入HashSet,最后汇总结果

首先插入测试数据aa.txt

//多线程插入测试数据
    public  void set() throws FileNotFoundException {
        File file = new File("E:\\aa.txt");
        PrintWriter pws = new PrintWriter(file);
        CountDownLatch latch = new CountDownLatch(9);
        ExecutorService executorService = Executors.newFixedThreadPool(9);
        for(int i=0;i<9;i++){
            executorService.execute(new SetClass("name+"+UUID.randomUUID().toString(),latch,file,pws));
        }

        try {
            latch.await(); //线程阻塞, 当latch中数量为0时,放行
        } catch (InterruptedException e) {
                e.printStackTrace();
        }
        executorService.shutdown();  //关闭线程
        pws.close();
    }

public class SetClass extends Thread{
        private final CountDownLatch countDownLatch;
        private File file;
        private PrintWriter pws;
        public SetClass(String name,  CountDownLatch countDownLatch1,File file,PrintWriter pws){
            super(name);
            this.countDownLatch = countDownLatch1;
            this.file = file;
            this.pws=pws;
        }

        @Override
        public void run() {
            for(int i=0;i<100000;i++){
                pws.println(UUID.randomUUID().toString());
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
            countDownLatch.countDown();
        }
    }

 大文件进行拆分,利用Hash取模将重复的数据存入同一个小文件

/**
     * 将文件hash取模之后放到不同的小文件中
     * @param targetFile 要去重的文件路径
     * @param splitSize 将目标文件切割成多少份hash取模的小文件个数
     * @return
     */
    public static File[] splitFile(String targetFile,int splitSize){
        File file = new File(targetFile);
        BufferedReader reader = null;
        PrintWriter[] pws = new PrintWriter[splitSize];
        File[] littleFiles = new File[splitSize];
        String parentPath = file.getParent();
        File tempFolder = new File(parentPath + File.separator + "test");
        if(!tempFolder.exists()){
            tempFolder.mkdir();
        }
        for(int i=0;i<splitSize;i++){
            littleFiles[i] = new File(tempFolder.getAbsolutePath() + File.separator + i + ".txt");
            if(littleFiles[i].exists()){
                littleFiles[i].delete();
            }
            try {
                pws[i] = new PrintWriter(littleFiles[i]);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            while ((tempString = reader.readLine()) != null) { // reader.readLine()逐行读取,避免一次性读完整个文件
                tempString = tempString.trim();
                if(tempString != ""){
                    //关键是将每行数据hash取模之后放到对应取模值的文件中,确保hash值相同的字符串都在同一个文件里面
                    int index = Math.abs(tempString.hashCode() % splitSize);
                    pws[index].println(tempString);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            for(int i=0;i<splitSize;i++){
                if(pws[i] != null){
                    pws[i].close();
                }
            }
        }
        return littleFiles;
    }

对小文件进行去重并合并结果

/**
     * 对小文件进行去重合并
     * @param littleFiles 切割之后的小文件数组
     * @param distinctFilePath 去重之后的文件路径
     * @param splitSize 小文件大小
     */
    public static void distinct(File[] littleFiles,String distinctFilePath,int splitSize){
        File distinctedFile = new File(distinctFilePath);
        FileReader[] frs = new FileReader[splitSize];
        BufferedReader[] brs = new BufferedReader[splitSize];
        PrintWriter pw = null;
        try {
            if(distinctedFile.exists()){
                distinctedFile.delete();
            }
            distinctedFile.createNewFile();
            pw = new PrintWriter(distinctedFile);
            Set<String> unicSet = new HashSet<String>();
            for(int i=0;i<splitSize;i++){
                if(littleFiles[i].exists()){
                    System.out.println("开始对小文件:" + littleFiles[i].getName() + "去重");
                    frs[i] = new FileReader(littleFiles[i]);
                    brs[i] = new BufferedReader(frs[i]);
                    String line = null;
                    while((line = brs[i].readLine())!=null){
                        if(line != ""){
                            unicSet.add(line);
                        }
                    }
                    for(String s:unicSet){
                        pw.println(s);
                    }
                    unicSet.clear();
                    System.gc();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e1){
            e1.printStackTrace();
        } finally {
            for(int i=0;i<splitSize;i++){
                try {
                    if(null != brs[i]){
                        brs[i].close();
                    }
                    if(null != frs[i]){
                        frs[i].close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //合并完成之后删除临时小文件
                if(littleFiles[i].exists()){
                    littleFiles[i].delete();
                }
            }
            if(null != pw){
                pw.close();
            }
        }
    }

 

标签:文件,splitSize,PrintWriter,File,tempString,new
From: https://www.cnblogs.com/lhc-hhh/p/18430278

相关文章

  • 前端读取PDF和DOCX文件(干货分享)
    ⚠️⚠️文前推荐一下......
  • linux操作系统和文件系统,命令(上)
    Linux是一个类似于windows的操作系统Linux操作系统的一种主要使用方式是通过终端软件;终端软件里只能使用键盘不能使用鼠标,在终端软件里通过输入命令完成各种任务clear命令可以删除终端窗口里的所有文字信息操作系统里用来管理文件的部分叫文件系统所有文件系统都采用分组方式......
  • Navicate如何导入文件到表中
    首先创建好表的栏目,另存为好数据文件。记得不仅表要设置好字符编码,数据文件另存为时也要配好字符集编码,否则中文是乱码。创建好后,选择导入数据文件。选择数据文件类型。选择数据文件路径,并配好字符集编码。选择分隔符。CRLF:代表"回车并换行"后就是下一个元组。Co......
  • MISC - 第四天(OOK编码,audacity音频工具,摩斯电码,D盾,盲文识别,vmdk文件压缩)
    前言各位师傅大家好,我是qmx_07,今天继续讲解MISC知识点FLAG附件是一张图片,尝试binwalk无果使用StegSolve工具DataExtract查看时发现PK字段,是大多数压缩包的文件头点击SaveBin保存zip文件解压缩失败使用修复软件:http://forspeed.onlinedown.net/down/95222_201706......
  • MFC 之获取文件路径和文件目录路径
    这篇文章我们来介绍一个界面程序中常见的功能,那就是通过点击按钮打开文件浏览对话框,选择对应的文件或者文件夹后,获取其路径,并在编辑中显示出来,当然也会顺带讲一下如果获取当前可执行文件的路径和目录。一、获取文件路径首先我们从工具栏中拖拽一个编辑框和按钮控件到主对话框中,......
  • Linux内核文件系统-虚拟文件系统-索引节点对象
    建议点击这里查看个人主页上的最新原文作者:陈孝松主页:chenxiaosong.com公网主页:replace_with_public_ip_or_delete_this_line哔哩哔哩:陈孝松课程:chenxiaosong.com/courses博客:chenxiaosong.com/blog贡献:chenxiaosong.com/contributions邮箱:chenxiaosong@ch......
  • Telegram Bot 本地 API 服务器发送大文件时超时
    我正在尝试使用本地API服务器发送大文件。但是当文件上传时,我收到错误aiogram.exceptions.TelegramNetworkError:HTTPClientsays-Requesttimeouterror.importasyncioimportloggingimportsysimportjsonfromaiogramimportBot,Dispatcher,htmlfrom......
  • asp.net 上传大文件大小控制方案
    原文链接:https://blog.csdn.net/zdw_wym/article/details/7160942需要注意的是:在保存文件时,您应该确保指定文件的完整路径,并确保为ASP.NET使用的帐户提供要存储文件的目录的写权限。上载大文件时,可使用Web.Config元素的maxRequestLength属性来增加文件大小的最大允许值,例如:......
  • 正确下载与验证凯立德DLL文件的步骤是什么?针对凯立德导航软件的DLL文件定制化方法
    正确下载与验证凯立德DLL文件的步骤以及针对凯立德导航软件的DLL文件定制化方法,可以归纳如下:正确下载与验证凯立德DLL文件的步骤访问官方渠道:首选访问凯立德官方网站或官方授权的下载渠道,以确保下载到的DLL文件是官方发布且未经过篡改的。(DirectX修复工具综合解决问题-......
  • 尘埃拉力赛D3D11.dll文件丢失:轻松解决尘埃拉力赛D3D11.dll丢失方案汇总
    当您在尝试启动《尘埃拉力赛》(DiRTRally)时遇到“找不到D3D11.dll”或“D3D11.dll文件丢失”的错误提示,这意味着您的计算机上缺少或损坏了Direct3D11API的一个重要组件。D3D11.dll文件是Windows系统中用于高性能图形渲染的关键文件之一,对于《尘埃拉力赛》这类需要高级图形处......