JavaAlgorithms
Elementary and no so elementary Java algorithms
|
00001 00009 package sort; 00010 00011 import java.io.BufferedInputStream; 00012 import java.io.BufferedOutputStream; 00013 import java.io.File; 00014 import java.io.FileInputStream; 00015 import java.io.FileOutputStream; 00016 import java.io.IOException; 00017 import java.io.ObjectInputStream; 00018 import java.io.ObjectOutputStream; 00019 import java.io.Serializable; 00020 import java.util.ArrayList; 00021 00035 public class MergeSortFile<T extends Comparable<T> & Serializable> { 00036 private static String TEMP_ROOT_NAME = "tempFile"; 00037 private final int mNumObjects; 00038 private MergeSort<T> mSort = new MergeSort<T>(); 00039 private int mFileCnt = 0; 00040 00053 protected class FileObjContainer { 00054 FileInputStream inStr = null; 00055 BufferedInputStream bufStr = null; 00056 ObjectInputStream objStr = null; 00057 boolean EOF = false; 00058 00059 public FileObjContainer(File inFile) throws IOException { 00060 inStr = new FileInputStream(inFile); 00061 bufStr = new BufferedInputStream(inStr); 00062 objStr = new ObjectInputStream(bufStr); 00063 } 00064 00065 public T readObj() throws IOException, ClassNotFoundException { 00066 T newObj = null; 00067 if ((!EOF) && bufStr.available() > 0) { 00068 newObj = (T) objStr.readObject(); 00069 } else { 00070 EOF = true; 00071 } 00072 return newObj; 00073 } 00074 00075 public void close() throws Throwable { 00076 super.finalize(); 00077 try { 00078 if (inStr != null) { 00079 inStr.close(); 00080 } 00081 if (bufStr != null) { 00082 bufStr.close(); 00083 } 00084 if (objStr != null) { 00085 bufStr.close(); 00086 } 00087 } catch (IOException e) { 00088 } 00089 } // finalize 00090 } // ================< class FileObjContainer >====================== 00091 00102 protected class ReadFileValues { 00103 private ArrayList<FileObjContainer> mObjFiles; 00104 private ArrayList<T> mValues; 00105 00106 public ReadFileValues(ArrayList<FileObjContainer> objFiles) throws ClassNotFoundException, IOException { 00107 this.mObjFiles = objFiles; 00108 mValues = new ArrayList<T>(); 00109 // initialize the mValues ArrayList with the first value from each 00110 // file 00111 for (FileObjContainer objFile : objFiles) { 00112 T obj = objFile.readObj(); 00113 mValues.add(obj); 00114 } 00115 } 00116 00126 protected int minIx(ArrayList<T> values) { 00127 int ix = -1; 00128 T minVal = null; 00129 for (int i = 0; i < values.size(); i++) { 00130 T tstVal = values.get(i); 00131 if (tstVal != null) { 00132 if (minVal == null) { 00133 minVal = tstVal; 00134 ix = i; 00135 } else if (minVal.compareTo((T) tstVal) > 0) { 00136 minVal = tstVal; 00137 ix = i; 00138 } 00139 } 00140 } 00141 return ix; 00142 } // minIx 00143 00144 public T getLeastVal() throws ClassNotFoundException, IOException { 00145 T leastVal = null; 00146 int ix = minIx(mValues); 00147 if (ix >= 0) { 00148 leastVal = mValues.get(ix); 00149 // read a new value to replace the one that will be returned 00150 T newValue = mObjFiles.get(ix).readObj(); 00151 mValues.set(ix, newValue); 00152 } 00153 return leastVal; 00154 } 00155 } // ================< class ReadFileValues >========================== 00156 00165 public MergeSortFile(int numObjs) { 00166 this.mNumObjects = numObjs; 00167 } 00168 00174 protected String nextTempFileName() { 00175 mFileCnt++; 00176 String tempFileName = String.format("%s%02d", TEMP_ROOT_NAME, mFileCnt); 00177 return tempFileName; 00178 } 00179 00193 protected File writeSortedBlock(ArrayList<T> objList, File parentDir) throws IOException { 00194 String tempFileName = nextTempFileName(); 00195 // create a temporary file in the parent directory 00196 File tempFile = new File(parentDir, tempFileName); 00197 FileOutputStream fileStr = null; 00198 BufferedOutputStream bufStr = null; 00199 ObjectOutputStream objOutStr = null; 00200 try { 00201 fileStr = new FileOutputStream(tempFile); 00202 bufStr = new BufferedOutputStream(fileStr); 00203 objOutStr = new ObjectOutputStream(bufStr); 00204 for (T obj : objList) { 00205 objOutStr.writeObject(obj); 00206 } 00207 objOutStr.flush(); 00208 } finally { 00209 try { 00210 if (fileStr != null) { 00211 fileStr.close(); 00212 } 00213 if (bufStr != null) { 00214 bufStr.close(); 00215 } 00216 if (objOutStr != null) { 00217 objOutStr.close(); 00218 } 00219 } catch (IOException e) { 00220 } 00221 } 00222 return tempFile; 00223 } // writeSortedBlock 00224 00251 protected File readAndSortBlock(BufferedInputStream bufStr, ObjectInputStream objStr, File parentDir) 00252 throws IOException, ClassNotFoundException { 00253 File tempFile = null; 00254 ArrayList<T> objList = new ArrayList<T>(); 00255 int objCnt = 0; 00256 while (objCnt < mNumObjects && (bufStr.available() > 0)) { 00257 T obj = (T) objStr.readObject(); 00258 objList.add(obj); 00259 objCnt++; 00260 } 00261 00262 if (objList.size() > 0) { 00263 mSort.mergeSort(objList); 00264 tempFile = writeSortedBlock(objList, parentDir); 00265 } 00266 return tempFile; 00267 } // readAndSortBlock 00268 00279 protected void mergeFiles(ArrayList<File> fileList, File outFile) throws IOException, ClassNotFoundException { 00280 if (fileList.size() > 0) { 00281 if (fileList.size() == 1) { 00282 File tempFile = fileList.get(0); 00283 tempFile.renameTo(outFile); 00284 } else { 00285 ArrayList<FileObjContainer> fileObjs = new ArrayList<FileObjContainer>(); 00286 for (int i = 0; i < fileList.size(); i++) { 00287 File file = fileList.get(i); 00288 fileObjs.add(new FileObjContainer(file)); 00289 } // for 00290 ReadFileValues fileReader = new ReadFileValues(fileObjs); 00291 FileOutputStream fileStr = null; 00292 BufferedOutputStream bufStr = null; 00293 ObjectOutputStream objOutStr = null; 00294 try { 00295 fileStr = new FileOutputStream(outFile); 00296 bufStr = new BufferedOutputStream(fileStr); 00297 objOutStr = new ObjectOutputStream(bufStr); 00298 T obj = null; 00299 while ((obj = fileReader.getLeastVal()) != null) { 00300 objOutStr.writeObject(obj); 00301 } 00302 objOutStr.flush(); 00303 } finally { 00304 try { 00305 for (FileObjContainer fileObj : fileObjs) { 00306 fileObj.close(); 00307 } 00308 } catch (Throwable t) { 00309 } 00310 try { 00311 if (fileStr != null) { 00312 fileStr.close(); 00313 } 00314 if (bufStr != null) { 00315 bufStr.close(); 00316 } 00317 if (objOutStr != null) { 00318 objOutStr.close(); 00319 } 00320 } catch (IOException e) { 00321 } 00322 } // finally 00323 } // else 00324 } // if 00325 } // mergeFiles 00326 00337 protected ArrayList<File> buildSortedFileList(File inFile) throws IOException, ClassNotFoundException { 00338 ArrayList<File> fileList = new ArrayList<File>(); 00339 FileInputStream fileStr = null; 00340 BufferedInputStream bufStr = null; 00341 ObjectInputStream objStr = null; 00342 try { 00343 fileStr = new FileInputStream(inFile); 00344 File parentDir = inFile.getParentFile(); 00345 bufStr = new BufferedInputStream(fileStr); 00346 objStr = new ObjectInputStream(bufStr); 00347 File tempFile = null; 00348 while ((tempFile = readAndSortBlock(bufStr, objStr, parentDir)) != null) { 00349 fileList.add(tempFile); 00350 } 00351 } finally { 00352 try { 00353 if (fileStr != null) { 00354 fileStr.close(); 00355 } 00356 if (bufStr != null) { 00357 bufStr.close(); 00358 } 00359 if (objStr != null) { 00360 objStr.close(); 00361 } 00362 } catch (IOException e) { 00363 } 00364 } 00365 return fileList; 00366 } // buildSortedFileList 00367 00377 public void sortFile(File inFile, File outFile) throws ClassNotFoundException, IOException { 00378 ArrayList<File> fileList = buildSortedFileList(inFile); 00379 mergeFiles(fileList, outFile); 00380 for (File file : fileList) { 00381 file.delete(); // delete the temporary files 00382 } 00383 } 00384 00385 }