java 对比txt大文件的方法

缘来又是你 2016-03-13 04:05:09
如题,本人比较菜,参考了网上众多方法,现在依然没有找到解决的办法。我要对比的文件很大,是用一个 1G多的txt文件对比多个大文件TXT(含有过G的),找到相同项,之后生成一个含有相同项的txt文件。现在每当我的文件比较大的时候就内存溢出了,有什么办法分片读取,或者多线程提高效率(多线程本人没用过)吗?
求大神 贴出具体的处理代码,感激不尽。若可以 所以分都给你都行。
贴出自己参考网上人修改的代码,现在用2百多M的对比2百M的文件没什么大问题,过G就OVER了。主要是到getText2那个方法的时候 应该也就是读取放到内存的时候 溢出了。 怎么改进呢,或者其他的好方法,
package com.java.test;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class FileCompare {
public static void main(String[] args) throws IOException {

FileCompare c = new FileCompare();
long starTime=System.currentTimeMillis();
List<String> list = new ArrayList<String>();
list.add("C:\\data\\201601_1_2659165.txt");
list.add("C:\\data\\201601_2_7897618.txt");
list.add("C:\\data\\201601_3_6982874.txt");
list.add("C:\\data\\201601_4_5418256.txt");
list.add("C:\\data\201601_5_6757133.txt");
list.add("C:\\data\\201601_6_38000026.txt");
list.add("C:\\data\\201601_7_3806464.txt");
list.add("C:\\data\\201601_8_4820159.txt");
Map map = c.compareFile2("D:/1.txt",list.toArray());
System.out.println("-------->"+map.get("Common"));
// System.out.println("-------->"+map.get("Commonset"));
long endTime=System.currentTimeMillis();
long Time=endTime-starTime;
System.out.println("执行耗费时间:"+Time);

}


/**
* 3.1 对比的第二个为多个
* @param file11 比较文件path
* @param file22 被比较文件数组path
* @return 比较后的信息Map key1:Commonset匹配集合;key2:Common匹配数
*/
public Map compareFile2(String file11,Object[] file22) {
Map resultmap = new HashMap();
File file = new File(file11);
Set fileTextSet = new HashSet();
try {
System.out.println("开始解析第一个("+file11+")");
getText2(file, fileTextSet);//解析第一个txt
System.out.println("解析第一个("+file11+")完毕");
Set resultset = new HashSet();//匹配总集合
int resultCommon = 0;//匹配总数
for(Object file2s:file22){
System.out.println("开始对比file2s:"+file2s.toString());
Set file2TextSet = new HashSet();
File file2 = new File(file2s.toString());
System.out.println("开始解析("+file2s.toString()+")");
getText2(file2, file2TextSet);//解析另一个txt
System.out.println("解析("+file2s.toString()+")对比完毕");
System.out.println("开始匹配"+file2s.toString());
Map re = compareSet2(fileTextSet, file2TextSet);
System.out.println("匹配"+file2s.toString()+"完毕");
Set a = (Set) re.get("Commonset");
int numCommon =(int) re.get("Common");
resultset.addAll(a);//将匹配的集合放入到总集合
resultCommon += numCommon;//将匹配的数量+到总数
}
resultmap.put("Commonset", resultset);
resultmap.put("Common", resultCommon);
return resultmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//3.2
private Map compareSet2(Set textSet, Set StextSet2) {
Map map = new HashMap();
Set commonset = new HashSet();//放入匹配的集合

int numOfCommon = 0, numOfBase = 0, numOfAdap = 0;
for (Iterator iterator = textSet.iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
if (StextSet2.contains(name)) {
System.out.println("common:" + name);//匹配项
commonset.add(name);//匹配项
numOfCommon++;
} else {
// System.out.println("1:" + name);//第一个文件项
}
numOfBase++;
}
for (Iterator iterator = StextSet2.iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
if (!textSet.contains(name)) {
// System.out.println("2:" + name);//第二个文件项
}
numOfAdap++;
}
map.put("Commonset", commonset);//匹配集合
map.put("Common", numOfCommon);//匹配数
map.put("firstFIleNum", numOfBase);//第一个文件数
map.put("SecondFIleNum", numOfAdap);//第二个文件数
System.out.println("Common: " + numOfCommon);//匹配数
System.out.println("1: " + numOfBase);//第一个文件数
System.out.println("2: " + numOfAdap);//第二个文件数
return map;
}
//3.3
private void getText2(File file, Set textSet) throws IOException {
System.out.println("进入到了getText2方法");
BufferedReader br = null;
InputStream is = null;
try {
is = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(is, "UTF-8"),10*1024*1024);// 用10M的缓冲读取文本文件
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
String text = lineStr.substring(lineStr.indexOf(""));// 按照需求切分
// System.out.println("text:"+text);
textSet.add(text);
}
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
}
}

/**
* 采用BufferedInputStream方式读取文件行数
* 这个方法没有在这个逻辑里用可以忽略
* @param filename
* @return
* @throws IOException
*/
public int count(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
while ((readChars = is.read(c)) != -1) {
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n')
++count;
}
}
is.close();
return count;
}

}


...全文
346 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
缘来又是你 2017-06-27
  • 打赏
  • 举报
回复
已经解决了, 核心的思路是归并算法, 果然 算法才是王道啊
缘来又是你 2016-03-15
  • 打赏
  • 举报
回复
引用 1 楼 bao110908 的回复:
肯定不能直接比了,内存中放不下。参考一下【布隆过滤器】或许能够帮到你。
我网上找到了个分片的方法,得到了索引,可是每一份依然执行的好慢。。。。,因为被对比文件很多 而且也有很大的,每当对比到大文件就狗带了
缘来又是你 2016-03-15
  • 打赏
  • 举报
回复
引用 1 楼 bao110908 的回复:
肯定不能直接比了,内存中放不下。参考一下【布隆过滤器】或许能够帮到你。
我在网上找到了一个将TXT 按字节分片的方法,速度很快http://www.tuicool.com/articles/VBFbA36,结合这个方法拿到的索引位置,差不多将一个较大的TXT文本分成了10份,然后每一份放到集合set中,这样内存貌似开销不是很大了,再用他去对比,但是效率依然超慢。我看了你再 http://bbs.csdn.net/topics/190144112 中的帖子发的方法,参考中,不知道适不适合我说的这个场景,还有你说的布隆 还高大上啊。。。不知道怎么用都。。。
rumlee 2016-03-13
  • 打赏
  • 举报
回复
分段处理啊,
  • 打赏
  • 举报
回复
肯定不能直接比了,内存中放不下。参考一下【布隆过滤器】或许能够帮到你。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧