教新手使用java如何對(duì)一個(gè)大的文本文件內(nèi)容進(jìn)行去重
更新時(shí)間:2021年06月22日 11:19:47 作者:wei503316325
用HashSet對(duì)內(nèi)容去重這個(gè)過(guò)程jvm會(huì)內(nèi)存溢出,只能首先將這個(gè)大文件中的內(nèi)容讀取出來(lái),對(duì)每行String的hashCode取模取正整數(shù),可用取模結(jié)果作為文件名,將相同模數(shù)的行寫入同一個(gè)文件,再單獨(dú)對(duì)每個(gè)小文件進(jìn)行去重,最后再合并
有內(nèi)存溢出風(fēng)險(xiǎn)的寫法:
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內(nèi)存溢出:
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)
通過(guò)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 將目標(biāo)文件切割成多少份hash取模的小文件個(gè)數(shù)
* @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 != ""){
//關(guān)鍵是將每行數(shù)據(jù)hash取模之后放到對(duì)應(yīng)取模值的文件中,確保hash值相同的字符串都在同一個(gè)文件里面
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;
}
/**
* 對(duì)小文件進(jìn)行去重合并
* @param littleFiles 切割之后的小文件數(shù)組
* @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("開始對(duì)小文件:" + 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();
}
//合并完成之后刪除臨時(shí)小文件
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);
}
}
總結(jié)
本篇文章的內(nèi)容就到這了,希望大家可以喜歡,也希望大家可以多多關(guān)注腳本之家的其他精彩內(nèi)容!
相關(guān)文章
SpringBoot @NotBlank錯(cuò)誤的解決方案
這篇文章主要介紹了SpringBoot @NotBlank錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket
這篇文章主要介紹了詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01
springmvc學(xué)習(xí)筆記-返回json的日期格式問(wèn)題的解決方法
本篇文章主要介紹了springmvc學(xué)習(xí)筆記-返回json的日期格式問(wèn)題的解決方法,解決了日期格式的輸出,有興趣的可以了解一下。2017-01-01
Idea如何使用Fast Request接口調(diào)試
這篇文章主要介紹了Idea如何使用Fast Request接口調(diào)試問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之前綴,中綴和后綴表達(dá)式
這篇文章主要為大家介紹了Java的前綴,中綴和后綴表達(dá)式 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-01-01

