Sunday, April 13, 2008

SequentialExtension - Java class



SequentialExtension is a Java class to create filenames with a sequential extension. Given a directory with file.001, file.002, file.005; what is the next sequential filename? Either file.003 or file.006 - this utility class will return either java.io.File based on your desire for infix mode (file.003) or not (file.006).

Get the Java source code for SequentialExtension.java.

A utility class for generating sequential file extensions.

Assume a directory with:

|- file.name.001
|- file.name.002
|- file.name.005

What is the next file name in the sequential set?

file.name.006 or maybe file.name.003

Depends on what you want to do.

The method nextSequentialFile will generate a File object to meet either need.



/*
* Copyright (c) 2003 David A. Koontz
* Licensed under the Open Software License version 2.0
*/

import java.io.*;

/**
*  Utility class for generating sequential file extensions.
*
*
*  Assume a directory with:

*     |- file.name.001
*     |- file.name.002
*     |- file.name.005
* What is the next file name in the sequential set?

* file.name.006 or maybe file.name.003

* Depends on what you want to do.
*
* The method nextSequentialFile will generate a
* File object to meet either need.
*
* @author  David A. Koontz
*/

public class SequentialExtension {



/**
* Finds the next file extension of a sequential extension.
*
* Given file.001, file.002, file.005 in a directory this
* method will return file.003 when infix == true
* or file.006 when infix == false.
*
* If baseName is null or empty string then every file within the
* directory is considered within the sequential set.
*
* @param directory   the directory in which to search
* @param baseName    the filename's base part
* @param infix  when true gaps in sequence will be infiled
* @return            the File with the next sequential number
     */
public File nextSequentialFile(File directory, String baseName, boolean infix) {
File seqFile = null;

        if( (directory==null) || (!directory.isDirectory()) )
               throw new IllegalArgumentException("Invalid directory");

if ( infix ) {
// start with *.000  or *.001
// int next = 1;  // if you want to start with *.001
// just for sanity we limit the sequence loop to *.999

for ( int next = 0; next < 1000; next++ ) {
// generate the next extension in sequential set
String numStr = makeNumericExtension(next);

seqFile = new File(directory, baseName + '.' + numStr);

if ( ! seqFile.exists() ) {
break;  // found a non-existant file name - break out of loop & return it
}
}


if ( seqFile == null ) {
throw new UnsupportedOperationException("All sequential files 000 - 999 exist for "+baseName+"!");
}
} else {
// not inclusive - meaning generate extension at end of current set
// so file.001, file.002, file.005 results in file.006
int max = findMaxSequentialExtension(directory, baseName);
int next = max + 1;

// generate the next extension in sequential set
String numStr = makeNumericExtension(next);

seqFile = new File( directory, baseName + '.' + numStr );


}

return seqFile;

}

/**
*  Generate a three digit extension (zero padded).
*
*  Like: "003" or "023" (also "4321").
*/
private static String makeNumericExtension(int number) {
String numStr = "" + number;
if ( numStr.length() == 1 )
   numStr = "00" + number;
else if ( numStr.length() == 2 )
   numStr = "0" + number;

return numStr;

}

/**
* Finds the next file extension of a sequential extension.
*
* Given file.001, file.002, file.005 in a directory this
* method will return file.003.
*
* If baseName is null or empty string then every file within the
* directory is considered within the sequential set.
*
* @param directory   the directory in which to search
* @param baseName    the filename's base part
* @return            the File with the next sequential number
     */
public File nextSequentialFile(File directory, String baseName) {
        if( (directory==null) || (!directory.isDirectory()) )
               throw new IllegalArgumentException("Invalid directory");
        // start with *.000  or *.001
        // int next = 1;  // if you want to start with *.001
// just for sanity we limit the sequence loop to *.999
        File seqFile = null;

        for ( int next = 0; next < 1000; next++ ) {
// generate the next extension in sequential set
String numStr = "" + next;
if ( numStr.length() == 1 )
   numStr = "00"+next;
else if ( numStr.length() == 2 )
   numStr = "0"+next;

seqFile = new File(directory, baseName + '.' + numStr);

if ( ! seqFile.exists() ) {
break;  // found a non-existant file name - break out of loop & return it
}
}

if ( seqFile == null ) {
throw new UnsupportedOperationException("All sequential files 000 - 999 exist for "+baseName+"!");
}

return seqFile;

}

    /**
     * Finds the max file extension of a sequential file.
     *
     * Given file.001, file.002, file.005 in a directory this
     * method will return 5.
     *
     * Uses a FileFilter to search the directory if baseName is
     * provided. If baseName is null or empty string then every
     * file within the directory is considered within the sequential set.
     *
     * @param directory   the directory in which to search
     * @param baseName    the filename's base part
     * @return            the max sequential number
     */
    private int findMaxSequentialExtension(File directory, String baseName) {
        if( (directory==null) || (!directory.isDirectory()) )
               throw new IllegalArgumentException("Invalid directory");
        // start with *.000
        // int maxValue = 0;  // if you want to start with *.001
        int maxValue = -1;
        File[] files;
        if ( baseName!=null && baseName.length()>0 ) {
           files = directory.listFiles(new BaseNameFilter(baseName));
        } else {
           files = directory.listFiles();
        }
        for(int i=0; i < files.length; i++) {
            // ignore directories & do not recurse into sub-dir
            if(files[i].isFile()) {
                String name = files[i].getName();
                int dotIndex = name.lastIndexOf('.');
                // if no dot lastIndexOf returns -1
                // what about unix hidden (dot) files
                if (dotIndex > 0) {
// only if there is a basename
String ext = name.substring(dotIndex+1);

System.out.println( "found ext = " + ext );
try {
int num = Integer.parseInt(ext);
if ( num > maxValue ) maxValue=num;
}catch(NumberFormatException nfe) {
; // ignore
}
}
            }
        }

        return maxValue;
    }



   /**
    *  Strips path and extension from a filename.
    *
    */
   public static String getBaseName( String name )
   {
      // strip path.
      String base = new File( name ).getName();
      // strip possible extension.
      int index = base.lastIndexOf( '.' );
      if( index != -1 )
         base = base.substring( 0, index );

      return base;
   }

   /**
    *  Strips path and extension from a filename.
    *
    *  example: path/file.name.txt  ->  file.name
    *
    * Note: define extension as the substring after the last dot.
    *
    */
   public static String getBaseName( File name )
   {
      // strip path.
      String base = name.getName();
      // strip possible extension.
      int index = base.lastIndexOf( '.' );
      if( index != -1 )
         base = base.substring( 0, index );

      return base;
   }


   /**
    *  Strips path and base name from a filename.
    *
    *  example: path/file.txt  ->  txt
    *
    * Note: define extension as the substring after the last dot.
    *
    * example: path/long.file.name.ext -> ext
    */
   public static String getFileExtension( File file, boolean keepDot )
   {
      // strip path
      String base = file.getName();
  // strip possible extension
      String extension = "";
      int index = base.lastIndexOf( '.' );
      if( index != -1 )
      {
         if( keepDot )
            extension = base.substring( index );
         else
            extension = base.substring( index + 1 );
      }
      return extension;
   }


    /**
     * A Filter for filenames of a given base name.
     *
     * For use in File.listFiles

     * 
     * File[] files = directory.listFiles(BaseNameFilter("MyFile"));
     * 

     * Would return MyFile.001, MyFile.002, MyFile.txt, etc.
     */
    class BaseNameFilter implements FileFilter {
       // inner class
       private String name;
       BaseNameFilter(String baseName) {
           name = baseName;
       }
       public boolean accept(File f) {
           //
           String bn = getBaseName(f.getName());
           // is file system case sensitive? how would I know?
           // shouldn't Java System know?
           // if ( name.equalsIgnoreCase(bn) ) {
           if ( name.equals(bn) ) {
               return true;
           }
           return false;
       }
    }

    /**
     * A Filter for filenames of a given extension.
     *
     * For use in File.listFiles

     * 
     * File[] files = directory.listFiles(ExtensionFilter("txt"));
     * 

     * Would return junk.txt, apple.txt, MyFile.txt, etc.
     */
    class ExtensionFilter implements FileFilter {
       // inner class
       private String name;
       ExtensionFilter(String extension) {
           name = extension;
       }
       public boolean accept(File f) {
           //
           String ext = getFileExtension(f, false);
           // is file system case sensitive? how would I know?
           // shouldn't Java System know?
           // if ( name.equalsIgnoreCase(ext) ) {
           if ( name.equals(ext) ) {
               return true;
           }
           return false;
       }
    }



    /**
     *  Unit testing the Filters & findMaxSequentialExtension()
     */
public static void main( String[] args ) {

File nextFile = null;
String baseName = "file.name";

SequentialExtension se = new SequentialExtension(".");

// generate the next extension (not infix) in sequential set

nextFile = se.nextSequentialFile(se.cwd, baseName, false);

try {
if ( nextFile.createNewFile() ) {
System.out.println("Created " + nextFile.getName() );
} else {
System.out.println("Failed to create " + nextFile.getName() );
}
} catch (IOException ex) {
System.out.println("Failed" + ex);
}

// generate the infixed extension within a sequential set

nextFile = se.nextSequentialFile(se.cwd, baseName, true);
try {
if ( nextFile.createNewFile() ) {
System.out.println("Created " + nextFile.getName() );
} else {
System.out.println("Failed to create " + nextFile.getName() );
}
} catch (IOException ex) {
System.out.println("Failed" + ex);
}

se.list(baseName);

/* This is program output after a few runs & deleting a few files
   Note the missing files (003 & 004).

found ext = 000
found ext = 001
found ext = 002
found ext = 005
found ext = 006
Created file.name.007
Created file.name.003
List of 'file.name' files:
   file.name.000
   file.name.001
   file.name.002
   file.name.005
   file.name.006
   file.name.007
   file.name.003

*/

se.list();
}

File cwd;

public SequentialExtension(String dir) {
cwd = new File(dir);
}

public void list(String basename) {
File[] files = cwd.listFiles(new BaseNameFilter(basename) );
System.out.println("List of '" + basename + "' files:");
for (int i = 0; i < files.length; i++) {
System.out.println("   "+ files[i].getName() );
}
}
public void list() {
File[] files = cwd.listFiles( );
System.out.println("List of files:");
for (int i = 0; i < files.length; i++) {
System.out.println("   "+ files[i].getName() );
}
}

}

/*
* Copyright (c) 2003 David A. Koontz
* Licensed under the Open Software License version 2.0
*/

Post a Comment