JavaAlgorithms
Elementary and no so elementary Java algorithms
sort/MergeSortFile.java
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables