教新手使用java如何对一个大的文本文件内容进行去重

目录
  • 有内存溢出风险的写法:
  • 总结

有内存溢出风险的写法:

	public static void distinct() {
		File ff = new File("G://password/all.txt");
		File distinctedFile = new File("G://password/all-distinced.txt");
		PrintWriter pw = null;
		Set<String> allHash = null;
		FileReader fr = null;
		BufferedReader br = null;
		try {
			pw = new PrintWriter(distinctedFile);
			allHash = new HashSet<String>();
			fr = new FileReader(ff);
			br = new BufferedReader(fr);
			String line = null;
			while((line=br.readLine())!=null){
				line = line.trim();
				if(line != ""){
					allHash.add(line);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(null != fr){
					fr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(null != br){
					br.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		for(String s:allHash){
			pw.println(s);
		}
		pw.close();
	}

jvm内存溢出:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
	at java.util.HashMap.newNode(HashMap.java:1734)
	at java.util.HashMap.putVal(HashMap.java:630)
	at java.util.HashMap.put(HashMap.java:611)
	at java.util.HashSet.add(HashSet.java:219)
	at encode.Main.distinct(Main.java:180)
	at encode.Main.main(Main.java:215)

通过hashCode取模拆分写法:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;

public class DistinctFileUtil {

	/**
	 * 将文件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) {
				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();
			}
		}
	}

	public static void main(String[] args) throws IOException {
		int splitSize = 20;
		File[] files = splitFile("G://test/bigfile.txt",splitSize);
		distinct(files,"G://test/bigfile-distinct.txt",splitSize);
	}
}

总结

本篇文章的内容就到这了,希望大家可以喜欢,也希望大家可以多多关注我们的其他精彩内容!

(0)

相关推荐

  • Shell实现文本去重并操持原有顺序

    简单来说,这个技巧对应的是如下一种场景 假设有文本如下 复制代码 代码如下: cccc aaaa bbbb dddd bbbb cccc aaaa 现在需要对它进行去重处理,这个很简单,sort -u就可以搞定,但是如果我希望保持文本原有的顺序,比如这里有两个aaaa,我只是希望去掉第二个aaaa,而第一个aaaa在bbbb的前面,去重后仍旧要在它前面,所以我期望的输出结果是 复制代码 代码如下: cccc aaaa bbbb dddd 当然,这个问题本身并不难,用C++或python写起来都很

  • python实现文本去重且不打乱原本顺序

    代码也是在网上找的,效率挺不错的,特别适合字典文件的去重 #coding=utf-8 import sys def open_txt(): #打开TXT文本写入数组 try: xxx = file(sys.argv[1], 'r') for xxx_line in xxx.readlines(): passlist.append(xxx_line) xxx.close() except: return 0 def write_txt(): #打开TXT文本写入数组 try: yyy = file

  • 教新手使用java如何对一个大的文本文件内容进行去重

    目录 有内存溢出风险的写法: 总结 有内存溢出风险的写法: public static void distinct() { File ff = new File("G://password/all.txt"); File distinctedFile = new File("G://password/all-distinced.txt"); PrintWriter pw = null; Set<String> allHash = null; FileRe

  • 教你用Java Swing做一个定时提醒工具

    前言 因为上下班的时候,老是忘记打卡(其实这不是重点,因为可以补卡嘛),重点是下班走的时候总是忘记关空调(谁最后走忘记关空调,罚100...) 我一开始的做法是,在主机上贴个便签,写上关空调三个大字,坐在电脑旁,只要你眼睛稍微一瞥,就是看到.可是依旧是该忘还得忘,那么明显一个便签贴在那,走的时候死活看不到,我有什么办法! 然后我就想做个弹窗提醒,一到下班的点,就弹窗提醒,然后就关空调,下班就关,总不会忘了吧.刚好那两天因为项目需要,我写了个vbs脚本,用vbs启动jar和exe程序这些.就想用v

  • 如何利用Java AWT 创建一个简易计算器

    目录 一.关于AWT 二.逻辑部分 1.对于数字按钮 2.对于算术按钮 3.对于等号按钮 4.对于清除按钮 5.对于退格按钮 6.特殊插件功能 7.==例如==: 三.GIF演示 四.附完整代码 摘要:手把手教你使用 Java AWT 创建一个简易计算器. 一.关于AWT AWT (抽象窗口工具包)是一个有助于构建 GUI 的 API (图形用户界面)基于 java 应用程序.GUI使用一些图形帮助用户交互.它主要由一组的类和方法所必需的,如在一个简化的方式创建和管理的GUI按钮,窗口,框架,文

  • 教你用Java实现一个简单的代码生成器

    前言 逆向工程从数据库表直接生成代码,是日常开发中常用的敏捷开发手段,常见的例如:mybatis-plus的代码生成器等 为什么要自己写代码生成器呢?MP的生成器不香吗?香! 但是自己写的工具用起来最顺手,可以随意扩展,想怎么玩就怎么玩,只要自己有想法,玩出花来都没问题,当然了,能力有限,现在还只能实现简单版本,更多骚操作自己发挥! 思路: 1.建立jdbc连接,执行查询sql,获取表结构信息. 2.在指定的路径上创建文件. 3.按照我们的布局排版要求,根据表结构信息拼接文件的内容. 4.将字符

  • Java语言的11大特点(Java初学者必知)

    Java简介 Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征. Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程  . Java具有简单性.面向对象.分布式.健壮性.安全性.平台独立与可移植性.多线程.动态性等特点 Java可以编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序等 . Java是一种简单的,面向对

  • 教你用Java实现RSA非对称加密算法

    一.非对称加密 非对称加密算法是一种密钥的保密方法. 非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥).公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密.因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法. 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方:甲方再用自己私钥对加密

  • 手把手教你用Java实现一套简单的鉴权服务

    前言 时遇JavaEE作业,题目要求写个简单web登录程序,按照老师的意思是用servlet.jsp和jdbc完成.本着要么不做,要做就要做好的原则,我开始着手完成此次作业(其实也是写实训作业的用户鉴权部分),而之前写项目的时候也有相关经验,这次正好能派上用场. 一.何为鉴权服务 引用百度百科的话说 鉴权(authentication)是指验证用户是否拥有访问系统的权利. 鉴权包括两个方面: 用户鉴权,网络对用户进行鉴权,防止非法用户占用网络资源. 网络鉴权,用户对网络进行鉴权,防止用户接入了非

  • 手把手教你使用Java实现在线生成pdf文档

    目录 一.介绍 二.案例实现 2.1添加iText依赖包 2.2简单实现 2.3复杂实现 2.4变量替换方式 三.总结 一.介绍 在实际的业务开发的时候,研发人员往往会碰到很多这样的一些场景,需要提供相关的电子凭证信息给用户,例如网银/支付宝/微信购物支付的电子发票.订单的库存打印单.各种电子签署合同等等,以方便用户查看.打印或者下载. 例如下图的电子发票! 熟悉这块业务的童鞋,一定特别清楚,目前最常用的解决方案是:把相关的数据信息,通过一些技术手段生成对应的 PDF 文件,然后返回给用户,以便

  • 教你使用Java实现扫雷小游戏(最新完整版)

    目录 效果展示 主类:GameWin类 底层地图MapBottom类 顶层地图MapTop类 底层数字BottomNum类 初始化地雷BottomRay类 工具GameUtil类 总结 大家好,我是orangemilk_,哈哈,学习Java已经到一个阶段啦,今天我们使用GUI来写一个扫雷小游戏吧! 效果展示 主类:GameWin类 package com.sxt; import javax.swing.*; import java.awt.*; import java.awt.event.Mou

  • Java实现贪吃蛇大作战小游戏的示例代码

    目录 效果展示 项目介绍 项目背景 总体需求 实现过程 代码展示 项目结构 总结 大家好,今天尝试用swing技术写一个贪吃蛇大作战小游戏,供大家参考. 效果展示 效果展示 一.游戏界面 二.得分情况 项目介绍 项目背景 “贪吃蛇大作战”游戏是一个经典的游戏,它因操作简单.娱乐性强,自从计算机实现以来,深受广大电脑玩家的喜爱,本项目基于Java技术,开发了一个 操作简单.界面美观.功能较齐全 的“贪吃蛇”游戏.通过本游戏的开发,达到学习Java技术和熟悉软件开发流程的目的. 总体需求  本系统主

随机推荐