两个上亿行的大文件取交集

转载 2012年03月23日 17:56:17

package com.fly.lee.bigfile;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BigFile {
 private List<String> subFileNameList = new ArrayList<String>();
 private String bigFilePath = "D:/bigfile/";

 private String bigFileName = "Source1.txt";
 private FileGenerator fGenerator = new FileGenerator();
 
 private static final int theMaxNumber = 10000000;
 private List<Integer> theContentWritingToSubFile = new ArrayList<Integer>(theMaxNumber);
 
 public void sortTheBigfile(String destination){
  splitTheBigFile();
  SourceFolder sFolder = new SourceFolder();
  sFolder.setFilenameList(subFileNameList);
  sFolder.setDestination(destination);
  try {
   sFolder.compareFiles();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  removeTheSubFiles();
 }
 
 public void setBigFilePath(String bigFilePath) {
  this.bigFilePath = bigFilePath;
 }
 
 public void setBigFileName(String bigFileName) {
  this.bigFileName = bigFileName;
 }
 
 private void removeTheSubFiles() {
  for(String fileName:subFileNameList){
   File file = new File(fileName);
   if(file.exists()&&file.canWrite()){
    System.out.println(fileName+":"+file.delete());;
   }
  }
 }

 public void splitTheBigFile(){
  System.out.println("begin to spliting the big files...");
  int counter = 0;
  File file = new File(bigFilePath+bigFileName);
        BufferedReader reader = null;
        FileReader fReader;
        int fileFlag = 1;
        try {
         fReader = new FileReader(file);
            reader = new BufferedReader(fReader);
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
             if(tempString.trim().equals("")){
              break;
             }
             int tempInt = Integer.valueOf(tempString);
             theContentWritingToSubFile.add(tempInt);
             if(isTheListFull(counter)){
              handleTheFullList(fileFlag);
              theContentWritingToSubFile.clear();
              fileFlag ++;
             }
            }
            handleTheFullList(fileFlag);
            fReader.close();
            reader.close();
            System.out.println("finishing the spliting work.");
        }catch(Exception e){
         e.printStackTrace();
        }
 }

 private void handleTheFullList(int fileFlag) throws Exception {
  System.out.println("handle the full list...");
  String tempFilePath = bigFilePath + fileFlag + ".txt";
  writeTheContentToSubFile(tempFilePath);
  subFileNameList.add(tempFilePath);
  theContentWritingToSubFile.clear();
  System.out.println("the full list is clear now...");
 }
 
 private void writeTheContentToSubFile(String tempFilePath) throws Exception {
  System.out.println("begin to write the content to sub file...");
  System.out.println("sub file path:"+tempFilePath);
  Collections.sort(theContentWritingToSubFile);
  fGenerator.setFileName(tempFilePath);
  fGenerator.setTheListNeedToWriteTofile(theContentWritingToSubFile);
  fGenerator.writeToFileFromTheList(true);
  System.out.println("finishing this loop of writing the content to sub file...");
 }
 
 private boolean isTheListFull(int counter) {
  return theContentWritingToSubFile.size() >= theMaxNumber;
 }
 
 public static void main(String[] args) {
  BigFile bf = new BigFile();
  bf.setBigFileName("Source1.txt");
  bf.sortTheBigfile("D:/bigfile/Source1_sorted.txt");
 }
}
SourceFolder.java: 主要负责对文件夹下拆分后的小文件进行比较并合并成一个新的有序文件。

package com.fly.lee.bigfile;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SourceFolder {
 private List<String> filenameList;
 private Map<Integer, Integer> numberCache;
 private List<BufferedReader> bufferedReaderList;
 private int endFlagNumber = 0;
 private List<Integer> contentListWritingToFile;
 private FileGenerator fileGenerator;
 private String destination = "D:/bigfile/AllSource.txt";
 

 public SourceFolder() {
  contentListWritingToFile = new ArrayList<Integer>();
  filenameList = new ArrayList<String>();
  bufferedReaderList = new ArrayList<BufferedReader>();
  fileGenerator = new FileGenerator();
 }

 public void setDestination(String destination) {
  this.destination = destination;
 }
 public void addFile(String filename) {
  this.filenameList.add(filename);
 }
 public void setFilenameList(List<String> filenameList) {
  this.filenameList = filenameList;
 }

 public void compareFiles() throws Exception {
  System.out.println("filenameList:"+filenameList);
  initTheBufferedReaderList();
  initTheNumberCache();
  while(!isAllFilesFinishTheComparing()){
   int theIndexOfReaderNeedingToMove = findTheLastIndexOfTheMinNumber();
   addTheNumberToFile(theIndexOfReaderNeedingToMove);
   updateNumberCache(theIndexOfReaderNeedingToMove);
  }
  addTheLastListToFile();
  closeAllIOStreams();
 }
 
 private void closeAllIOStreams() throws IOException {

  for(BufferedReader bReader:bufferedReaderList){
   if(bReader != null){
    bReader.close();
   }
  }
  
 }

 private int findTheLastIndexOfTheMinNumber() {
  int theIndexOfTheMinNumber = 0;
  int mixNumber = getTheFirstNumberFromTheCache();
  for (int index = 0; index < numberCache.size(); index++) {
   if(numberCache.get(index) == null){
    continue;
   }
   int theNumberWillBeCompared = numberCache.get(index);
   if (mixNumber >= theNumberWillBeCompared) {
    mixNumber = theNumberWillBeCompared;
    theIndexOfTheMinNumber = index;
   }
  }
  return theIndexOfTheMinNumber;
 }

 private int getTheFirstNumberFromTheCache() {
  for (int index = 0; index < numberCache.size(); index++) {
   if(numberCache.get(index) == null){
    continue;
   }
   return numberCache.get(index);
  }
  return 0;
 }

 private void addTheNumberToFile(int theIndexOfReaderNeedingToMove) throws Exception {
  contentListWritingToFile.add(numberCache.get(theIndexOfReaderNeedingToMove));
  if(contentListWritingToFile.size() == 1000000){
   fileGenerator.setTheListNeedToWriteTofile(contentListWritingToFile);
   fileGenerator.setFileName(destination);
   fileGenerator.writeToFileFromTheList( false);
   contentListWritingToFile.clear();
  }
 }
 
 private void updateNumberCache(int index) throws Exception {
  BufferedReader bufferedReader = bufferedReaderList.get(index);
  String tempString = null;
  if ((tempString = bufferedReader.readLine()) != null) {
   if (!"".equals(tempString.trim())) {
    int tempInt = Integer.valueOf(tempString);
    numberCache.put(index, tempInt);
   }
  } else {
   numberCache.put(index, null);
   endFlagNumber ++;
  }
 }
 
 private void addTheLastListToFile() throws Exception {
  fileGenerator.setTheListNeedToWriteTofile(contentListWritingToFile);
  fileGenerator.setFileName(destination);
  fileGenerator.writeToFileFromTheList(false);
 }

 

 private void initTheBufferedReaderList() throws FileNotFoundException {
  System.out.println("begin to initial the buffered reader...");
  for (String filename : filenameList) {
   BufferedReader bufferedReader = new BufferedReader(new FileReader(
     filename));
   bufferedReaderList.add(bufferedReader);
  }
  System.out.println("finish initialing the buffered reader...");
 }

 private void initTheNumberCache() throws Exception {
  System.out.println("begin to initial the number cache...");
  numberCache = new HashMap<Integer, Integer>(filenameList.size());
  for (int index = 0; index < filenameList.size(); index++) {
   updateNumberCache(index);
  }
  System.out.println("finish initialing the number cache...");
 }

 private boolean isAllFilesFinishTheComparing() {
  
  return endFlagNumber == filenameList.size();
 }
}

FileGenerator.java主要是负责将生成好的链表写入到一指定的文件中,可以选择是覆盖文件或者是在文件后添加。里面也有生成上亿行文件的方法(测试时可以事先用此方法生成大文件。 : ) ).

package com.fly.lee.bigfile;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FileGenerator {
 private int wholeLineNumber = 100000000;

 private List<Integer> theListNeedToWriteTofile;
 private String fileName;
 private FileWriter fWriter = null;

 // public void write
 public static void main(String[] args) {
  String fileName = "D:/bigfile/Source_yiwan.txt";
  FileGenerator fileGenerator = new FileGenerator();
  fileGenerator.setFileName(fileName);
  try {
   fileGenerator.createRandomFile();
   fileGenerator.closeFileWriter();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 public void setFileName(String fileName) {
  this.fileName = fileName;
 }

 public void setWholeLineNumber(int wholeLineNumber) {
  this.wholeLineNumber = wholeLineNumber;
 }
 
 public void setTheListNeedToWriteTofile(List<Integer> theListNeedToWriteTofile) {
  this.theListNeedToWriteTofile = theListNeedToWriteTofile;
 }
 public void createRandomFile() throws Exception {
  int listSize = 10000000;
  theListNeedToWriteTofile = new ArrayList<Integer>(listSize);
  for(int i = 0; i < wholeLineNumber; i ++){
   int tempRandomInt = (int)(Math.random()*100000000);
   theListNeedToWriteTofile.add(tempRandomInt);
   if(theListNeedToWriteTofile.size()==listSize){
    System.out.println("begin to write to the file...");
    writeToFileFromTheList(false);
    theListNeedToWriteTofile.clear();
    System.out.println("finish this loop...");
   }
  }
  writeToFileFromTheList(false);
}

 public void writeToFileFromTheList(boolean isNeedToCreateNewFile) throws Exception {
  System.out.println("write the content to file...");
  try {
   if(isNeedToCreateNewFile){
    createNewFile(fileName);
   }
   StringBuilder contentWritingToFile = new StringBuilder();
   int cycleLineNumber = 1000000;
   int counter = 0;
   fWriter = new FileWriter(fileName,true);
   for(int index = 0; index < theListNeedToWriteTofile.size(); index ++){
    int tempRandomInt = theListNeedToWriteTofile.get(index);
    contentWritingToFile.append(tempRandomInt+"\n");
    if(counter == cycleLineNumber){
     fWriter.append(contentWritingToFile.toString());
     counter = 0;
     contentWritingToFile = new StringBuilder();
    }
   }
//   while(theListNeedToWriteTofile.size() != 0){
//    int tempRandomInt = theListNeedToWriteTofile.remove(0);
//    contentWritingToFile.append(tempRandomInt+"\n");
//    if(counter == cycleLineNumber){
//     fWriter.append(contentWritingToFile.toString());
//     counter = 0;
//     contentWritingToFile = new StringBuilder();
//    }
//   }
   fWriter.append(contentWritingToFile.toString());
   System.out.println("done..........");
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally{
   closeFileWriter();
  }
 }

 private void closeFileWriter() throws IOException{
  if(fWriter != null){
   fWriter.close();
  }
 }
 private void createNewFile(String fileName) throws IOException {
  File file = new File(fileName);
  if(file.delete()){
   file.createNewFile();
  }
 }
}

至此,完成了大文件的排序。至于下一步就是对着两个有序的大文件进行遍历比较了,
1.两个索引分别指向两个大文件的第一行。
2.如果两个索引所指的数据一样,记录当前数据到新的文件,并将两个指针分别下移一位。
如果二者不相等,则将数据较小的指针下移一位。
3.判断是否到其中一个文件的结尾,如果是,结束比较,否则重复步骤2。
这样就可以取出二者的交集,代码到此结束。

原地址:http://www.iteye.com/topic/1121936

相关文章推荐

面试--超大文件取交集

如果仅仅只是要取两个文件中都存在的数字,而不用管这个数字在两个文件中出现的次数的话,用BitSet就行了。 这个昨天有人讨论过,说给40亿个整数排序。 用数组显然是不行的,太大了,一个整形...
  • wmq534
  • wmq534
  • 2014年08月20日 18:47
  • 720

典型的Top K算法_找出一个数组里面前K个最大数...或找出1亿个浮点数中最大的10000个...一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存,

Top K 算法详解 应用场景:         搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。         假设目前有一千万个记录(...

易语言大文件取MD5不卡带进度

  • 2017年11月18日 14:02
  • 5KB
  • 下载

取两个集合的交集

  • 2013年05月21日 16:59
  • 1KB
  • 下载

如何求两个文件的交集、并集和差集?------sort和uniq闪亮登场

在日常开发中, 经常要对一些数据进行处理。 写个程序吧, 也可以实现, 但蛮麻烦的, 有些时候根本没有必要。 现在, a.txt和b.txt两个文件的数据都是逐行呈现的, 我们来说说如何求他们的交集、...
  • stpeace
  • stpeace
  • 2015年12月26日 13:35
  • 1887

C盘大文件扫描

  • 2017年11月16日 16:14
  • 617KB
  • 下载

查看大文件工具

  • 2017年10月27日 13:57
  • 6.47MB
  • 下载

linux 处理两个文件的并集,交集,计数

来源:IT技术博客大学习 标签:sortuniq   1. 取出两个文件的并集(重复的行只保留一份)   cat file1 file2 | sort | uniq   2...

局域网大文件快速传输工具

  • 2015年03月04日 16:16
  • 786KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:两个上亿行的大文件取交集
举报原因:
原因补充:

(最多只允许输入30个字)