1. 程式人生 > >大文字檔案(接近7GB): 統計頻數,Top K問題求解

大文字檔案(接近7GB): 統計頻數,Top K問題求解

自己實踐如下

1 產生了一個1G行,每行一個[0,100000]區間的整數

2 top n 求解:

2.1 大檔案分成小檔案

把這個7G左右的大檔案,按照讀入數字的hashcode值分成1024個小檔案(每個檔案平均最大就7M左右)

這裡寫圖片描述

這裡寫圖片描述

2.2 小檔案統計

對每個小檔案,可以用堆,hash,內部排序等等方法進行處理;
本例使用Java的HashMap

2.3 小檔案的統計結果 再做一次統計 求出出現頻數最高的那個數

結果:

這裡寫圖片描述

java原始碼

import java.io.*;
import java.util.*;

class IP implements Serializable {  

    private
static final long serialVersionUID = -8903000680469719698L; private String ip = ""; private int count; public IP(String ip2, Integer integer) { this.ip = ip2; this.count = integer; } public int getCount() { return count; } public
String getIp() { return ip; } public void setCount(int count) { this.count = count; } public void setIp(String ip) { this.ip = ip; } } public class Data { static String fileLoc = "D:\\hadoop\\numsout\\nums.txt"; /** * 將打檔案hash成1024個小檔案 * * @throws
FileNotFoundException * @throws IOException */
private static void hashToSmallFiles() throws FileNotFoundException, IOException { BufferedReader br = new BufferedReader(new FileReader(fileLoc)); String ip = ""; HashMap<String, FileWriter> fileWriters = new HashMap<String, FileWriter>(); while ((ip = br.readLine()) != null) { int tmp = Math.abs(ip.hashCode() % 1024); String fileName = fileLoc + tmp + ".txt"; FileWriter fw = null; if (fileWriters.containsKey(fileName)) { fw = fileWriters.get(fileName); } else { fw = new FileWriter(fileName, true); fileWriters.put(fileName, fw); } fw.write(ip + "\n"); } br.close(); for (FileWriter ff : fileWriters.values()) { ff.close(); } } /** * 利用HashMap<> 統計每個小檔案頻數最高的ip; * @return 所有小檔案的結果 組成List 返回 * @throws FileNotFoundException * @throws IOException */ private static List<IP> countEverySmallFile() throws FileNotFoundException, IOException { List<IP> list = new ArrayList<IP>(); for (int i = 0; i < 1024; i++) { File file = new File(fileLoc + i + ".txt"); if (file.exists()) { long startTime = System.currentTimeMillis(); BufferedReader br1 = new BufferedReader(new FileReader(file)); String ip1 = ""; HashMap<String, Integer> hm = new HashMap<String, Integer>(); while ((ip1 = br1.readLine()) != null) { if (!hm.containsKey(ip1)) { hm.put(ip1, 1); } else { hm.put(ip1, hm.get(ip1) + 1); } } IP[] ips = new IP[hm.size()]; int index = 0; for (String temp : hm.keySet()) { ips[index] = new IP(temp, hm.get(temp)); index++; } int max = 0; for (int j = 1; j < ips.length; j++) { if (ips[j].getCount() > ips[max].getCount()) { max = j; } } list.add(ips[max]); long endTime = System.currentTimeMillis(); System.out.println("已經統計檔案:" + fileLoc + i + ".txt,用時:" + (endTime - startTime) + " 毫秒"); } } return list; } /** * 從每個檔案出現頻率最高ip中,計算出所有檔案中出現頻率最高ip。 * * @param list */ private static IP calculateResult(List<IP> list) { IP[] ips = new IP[list.size()]; ips = list.toArray(ips); int max = 0; for (int j = 1; j < ips.length; j++) { if (ips[j].getCount() > ips[max].getCount()) { max = j; } } return ips[max]; } public static void findIp() throws IOException, ClassNotFoundException { long start = System.currentTimeMillis(); //hashToSmallFiles(); long end1 = System.currentTimeMillis(); System.out.println("將大檔案對映成小檔案,用時:" + (end1 - start) + "毫秒"); System.out.println("將大檔案對映成小檔案,約:" + (end1 - start) / 60000 + "分鐘"); // 測試時大約28分鐘 System.out.println("對映到小檔案完成,開始統計每個小檔案中出現頻率最高的ip"); long start1 = System.currentTimeMillis(); List<IP> list = countEverySmallFile(); long end2 = System.currentTimeMillis(); System.out.println("統計所有檔案共用時:" + (end2 - start1) + " 毫秒"); System.out.println("統計所有檔案共用時,約:" + (end2 - start1) / 60000 + "分鐘"); // 測試時大約13分鐘 System.out.println("統計完成,開始計算所有ip中出現頻率最高的ip"); IP ip = calculateResult(list); System.out.println("訪問次數最多的ip是:" + ip.getIp() + ":" + ip.getCount()); long end = System.currentTimeMillis(); System.out.println("公用時:" + (end - start) + "毫秒"); } // 產生大檔案 public static void getBigFile() { try { File file = new File(fileLoc); if(!file.exists()) { //如果不存在則建立 file.createNewFile(); System.out.println("檔案建立完成,開始寫入"); } FileWriter fw = new FileWriter(file); //建立檔案寫入 BufferedWriter bw = new BufferedWriter(fw); //產生隨機資料,寫入檔案 Random random = new Random(); for(int i=0;i<1024*1024*1024;i++) { int randint = (int)Math.floor((random.nextDouble()*100000.0));//產生【0,10000】之間隨機數 bw.write(String.valueOf(randint)); //寫入一個隨機數 bw.newLine(); //新的一行 } bw.close(); fw.close(); System.out.println("檔案寫入完成"); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { //getBigFile(); // 產生檔案:有1024*1024*1024行(1G行),每一行一個數字 findIp(); System.out.println("Finished"); } }