1. package
2.   
3. import
4. import
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13. import
14. import
15. import
16.   
17. /** 
18.  *  
19.  * 外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存, 
20.  * 需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。 
21.  * 外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装人内存的部分, 
22.  * 分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行归并排序。 
23.  *  
24.  * @author jia.hej 
25.  * 
26.  * @version $Id: MergeSort.java, v 0.1 2009-8-7 下午03:53:51 jia.hej Exp $ 
27.  */
28. public class
29.   
30. /** 十 */
31. private static long   TEN              = 10;   
32. /** 百 */
33. private static long   HUNDRED          = 100;   
34. /** 千 */
35. private static long   THOUSAND         = 1000;   
36. /** 万 */
37. private static long   MILLION          = 10000;                 //1078  00:00:01 078 
38. /** 十万 */
39. private static long   TEN_MILLION      = 100000;                //9656  00:00:09 656 
40. /** 百万 */
41. private static long   HUNDRED_MILLION  = 1000000;               //93733  00:01:33 733 
42. /** 千万 */
43. private static long   THOUSAND_MILLION = 10000000;              //970144  00:16:10 144 
44. /** 亿 */
45. private static long   BILLION          = 100000000;   
46. /** 十亿 */
47. private static long   TEN_BILLION      = 1000000000;   
48. /** 百亿 */
49. private static long
50. /** 千亿 */
51. private static long
52.   
53. private static String INPUT_FILE       = "c:\\test\\input.txt";   
54.   
55. private static String OUTPUT_FILE      = "c:\\test\\output.txt";   
56.   
57. /** 拆分大小 */
58. private static int    SPLIT_SIZE       = 10 * 10000;   
59.   
60. private static int
61.   
62. public static void main(String[] args) throws
63. "c:\\test");   
64.         createFile(INPUT_FILE);   
65.         numSize = createRandomNum(THOUSAND_MILLION);   
66.   
67.         sortFile(INPUT_FILE);   
68.   
69. long
70. "begin="
71.   
72. //拆分文件 
73.         splitFile(INPUT_FILE, numSize);   
74.   
75. new
76. new File("c:\\test\\temp");   
77.         File[] files = dir.listFiles();   
78. for (int i = 0; i < files.length; i++) {   
79.             File file = files[i];   
80.             splitFilePathList.add(file.getAbsolutePath());   
81.         }   
82. //合并文件 
83.         createFile(OUTPUT_FILE);   
84.         mergeFile(splitFilePathList, OUTPUT_FILE);   
85.   
86. long
87. "end="
88. "end-begin="
89. new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");   
90.         System.out.println(simpleDateFormat.format(endTime - beginTime));   
91.   
92. //删除拆分文件 
93.         System.gc();   
94. new String[] { "cmd", "/c", "del", "c:\\test\\temp\\*.txt"
95.     }   
96.   
97. private static void sortFile(String path) throws
98. new
99. new
100. new
101. new
102.         String value;   
103. while ((value = bufferedReader.readLine()) != null) {   
104.             set.add(Integer.parseInt(value));   
105.         }   
106.         bufferedReader.close();   
107.         fileReader.close();   
108. "c:\\test\\input排序.txt");   
109. "c:\\test\\input排序.txt", set, false);   
110.     }   
111.   
112. /** 
113.      * 拆分文件 
114.      *  
115.      * @param inputPath 
116.      * @param numSize 
117.      * @throws Exception 
118.      */
119. private static void splitFile(String inputPath, int numSize) throws
120. new
121. new
122. new
123. new
124.         String str;   
125. "c:\\test\\temp");   
126. if
127. int count = 1;   
128. int fileNum = 1;   
129. while ((str = bufferedReader.readLine()) != null) {   
130.                 set.add(Integer.parseInt(str));   
131. //超过拆分数,写入子文件 
132. if
133. "c:\\test\\temp\\" + fileNum + ".txt");   
134. "c:\\test\\temp\\" + fileNum + ".txt", set, false);   
135.                     set.clear();   
136. 0;   
137.                     fileNum++;   
138.                 }   
139. //读取文件当前行数 
140.             }   
141.         }   
142. //总量未达到拆分数,写入子文件 
143. else
144. while ((str = bufferedReader.readLine()) != null) {   
145.                 set.add(Integer.parseInt(str));   
146.             }   
147. "c:\\test\\temp\\1.txt");   
148. "c:\\test\\temp\\1.txt", set, false);   
149.         }   
150. if (bufferedReader != null) {   
151.             bufferedReader.close();   
152.         }   
153. if (fileReader != null) {   
154.             fileReader.close();   
155.         }   
156.     }   
157.   
158. /** 
159.      * 合并文件 
160.      *  
161.      * <p> 
162.      *    1.txt(1、3、5、7、9)和2.txt(6、8、9)<br/> 
163.      *    首先1和6进入treeset。 <br/> 
164.      *    输出1,发现是来自于1.txt的,再读入3,此时set中的元素是6和3。<br/>  
165.      *    输出3,发现还是来自于1.txt的,再读入5,此时set中的元素是6和5。 <br/> 
166.      *    输出5,发现还是来自于1.txt的,再读入7,此时set中的元素是6和7。 <br/> 
167.      *    输出6,发现来自于2.txt的,读入8,此时set中的元素是8和7。 <br/> 
168.      *    输出7,发现来自于1.txt的,读入9,此时set中的元素是8和9。 <br/> 
169.      *    输出8,发现来自于2.txt的,读入9,此时set中的元素是9和9。 
170.      * </p> 
171.      *  
172.      * @param splitFilePathList 
173.      * @param outputPath 
174.      * @throws Exception 
175.      */
176. private static void
177. throws
178. //fileInfo添加到set 
179. new TreeSet<FileInfo>(new
180. if
181. for (int i = 0; i < splitFilePathList.size(); i++) {   
182. new
183. new
184. new
185.   
186. new
187.                 String splitFilePath = splitFilePathList.get(i);   
188.                 fileInfo.setFileNum(Integer.parseInt(splitFilePath.substring(splitFilePath   
189. "\\") + 1, splitFilePath.indexOf(".txt"))));//文件号 
190. //reader引用 
191.                 String value = bufferedReader.readLine();   
192. if (value != null) {   
193. //当前值 
194. 1);//当前行号 
195.                     fileInfoSet.add(fileInfo);   
196.                 }   
197.             }   
198.         }   
199.   
200. new
201. boolean isSplit = false;   
202. int count = 1;   
203. //输出set元素 
204. while
205.             FileInfo currentFileInfo = fileInfoSet.first();   
206.             valueSet.add(Integer.parseInt(currentFileInfo.getValue()));   
207. //拆分批量写入文件 
208. if
209. true);   
210.                 valueSet.clear();   
211. true;   
212.             }   
213.   
214. //clone fileInfo 
215. new
216.             nextFileInfo.setFileNum(currentFileInfo.getFileNum());   
217.             nextFileInfo.setLineNum(currentFileInfo.getLineNum());   
218.             nextFileInfo.setValue(currentFileInfo.getValue());   
219.             nextFileInfo.setReader(currentFileInfo.getReader());   
220.   
221. boolean
222.   
223. //未到文件末尾,set中fileInfo重新排序 
224. if
225. if
226.                     fileInfoSet.add(nextFileInfo);   
227.                 }   
228.             }   
229. //已到文件末尾,从set中移除该fileInfo 
230. else
231.                 fileInfoSet.remove(currentFileInfo);   
232.             }   
233.   
234. "----- MergeFile:" + count++ + " -----");   
235. "fileNum="
236. "lineNum="
237. "value="
238. "----------------------------");   
239.         }   
240.   
241. //从未拆分过则一次性写入文件 
242. if (valueSet.size() > 0
243. false);   
244.         }   
245. //曾拆分过剩余部分写入文件 
246. else if (valueSet.size() > 0
247. true);   
248.         }   
249.     }   
250.   
251. /** 
252.      * 生成随机数 
253.      *  
254.      * @param numSize 
255.      * @return 
256.      * @throws Exception 
257.      */
258. private static int createRandomNum(long numSize) throws
259. new
260. int count = 0;   
261. boolean isSplit = false;   
262. while
263. int num = (int) (Math.random() * numSize + 1);   
264. if
265.                 count++;   
266.             }   
267. //拆分批量写入文件 
268. if
269. true);   
270.                 set.clear();   
271. true;   
272.             }   
273.         }   
274.   
275. //从未拆分过则一次写入文件 
276. if (set.size() > 0
277. false);   
278.         }   
279. //曾拆分过剩余部分写入文件 
280. else if (set.size() > 0
281. true);   
282.         }   
283. return
284.     }   
285.   
286. private static void
287. new
288. if
289. if
290. " is create.");   
291.             }   
292.         }   
293.     }   
294.   
295. private static void createFile(String path) throws
296. new
297. if
298. if
299. " is create.");   
300.             }   
301.         }   
302.     }   
303.   
304. private static void writeFile(String path, Set<Integer> set, boolean isAppend) throws
305. new
306. new FileWriter(file, isAppend);// 第二个参数表示:是否为追加模 
307. new
308.         Iterator<Integer> iterator = set.iterator();   
309. while
310.             bufferedWriter.write(iterator.next().toString());   
311.             bufferedWriter.newLine();   
312.         }   
313.         bufferedWriter.flush();   
314. if (bufferedWriter != null) {   
315.             bufferedWriter.close();   
316.         }   
317. if (fileWriter != null) {   
318.             fileWriter.close();   
319.         }   
320.     }   
321. }  
322. package
323.   
324. import
325.   
326. /** 
327.  *  
328.  * 文件信息 
329.  *  
330.  * @author jia.hej 
331.  * 
332.  * @version $Id: FileInfo.java, v 0.1 2009-8-1 上午02:11:30 jia.hej Exp $ 
333.  */
334. public class
335.   
336. /** 
337.      * 文件号 
338.      */
339. private int
340.   
341. /** 
342.      * 当前行号 
343.      */
344. private int            lineNum = 0;   
345.   
346. /** 
347.      * 当前值 
348.      */
349. private
350.   
351. /** 
352.      * BufferedReader引用 
353.      */
354. private
355.   
356. public boolean readNextValue() throws
357.         String value;   
358. if ((value = this.reader.readLine()) != null) {   
359. this.value = value;   
360. this.lineNum++;   
361. return true;   
362. else
363. this.reader.close();   
364. return false;   
365.         }   
366.     }   
367.   
368. public int
369. return
370.     }   
371.   
372. public void setFileNum(int
373. this.fileNum = fileNum;   
374.     }   
375.   
376. public int
377. return
378.     }   
379.   
380. public void setLineNum(int
381. this.lineNum = lineNum;   
382.     }   
383.   
384. public
385. return
386.     }   
387.   
388. public void
389. this.value = value;   
390.     }   
391.   
392. public
393. return
394.     }   
395.   
396. public void
397. this.reader = reader;   
398.     }   
399. }  
 
1. package
2.   
3. import
4.   
5. /** 
6.  *  
7.  * 文件比较器 
8.  *  
9.  * @author jia.hej 
10.  * 
11.  * @version $Id: FileInfoComparator.java, v 0.1 2009-8-7 下午01:42:05 jia.hej Exp $ 
12.  */
13. public class FileInfoComparator implements
14.   
15. public int
16. if
17. return
18.         }   
19. //如果存在重复值则使用文件号比较 
20. else
21. return
22.         }   
23.     }   
24.   
25. }