de.unibi.techfak.jpredictor.sequences
Class MultiFileReader

java.lang.Object
  extended by java.io.Reader
      extended by de.unibi.techfak.jpredictor.sequences.MultiFileReader
All Implemented Interfaces:
java.io.Closeable, java.lang.Readable

public class MultiFileReader
extends java.io.Reader

A MultiFileReader represents the logical concatenation of other Readers. It starts out with an ordered collection of streams and reads from the first one until end of file is reached, whereupon the delimiter string is included and then it reads from the second one, and so on, until end of file is reached on the last of the contained Readers. Thus, it works similar to the SequenceInputStream class.

The purpose of this class is to make sure mark() and reset() function properly. Thus it is recommended to add readers by giving the filenames. The class then creates ResetableReader from the filenames and redirects attempts to mark and reset to the stream.

While reseting it may be that a file must be reopened. Thus thrown IOExceptions may be FileNotFoundException instead.


Field Summary
private  java.io.Reader actReader
          The reader actually used for read and write operations.
private  int actualReader
          The actual position in the readers vector.
private  java.util.Vector filenames
          The storage container of the readers filenames.
private  int markedReader
          The reader marked.
private  boolean markSupported
          Changed when adding Readers through one of the add-methods.
private  java.lang.String readerDelimiter
          The string used as a delimiter between the different reader in readers.
private  java.util.Vector readers
          The storage container of the subsequent readers.
 
Fields inherited from class java.io.Reader
lock
 
Constructor Summary
MultiFileReader(java.lang.String delimiter)
          Constructs a new MultiFileReader object with the given reader delimiter.
 
Method Summary
 void add(java.io.Reader reader)
          Adds a Reader to the underlying storage container.
 void add(java.lang.String filename)
          Adds a new ResetableReader to the vector of subsequence readers.
 void close()
          Closes and disbands all Readers stored in this class.
static java.lang.String filesToString(java.io.File[] files)
          Joins the filenames of all given Files into one string.
 java.io.Reader get(int index)
          Returns a reader for a given index.
 java.lang.String getFilename(int index)
          Returns the filename for a given index.
static java.io.Reader getReader(java.lang.String names)
          Creates either a MultiFileReader or a ResetableReader from the filenames comprised in names.
 void mark(int readAheadLimit)
          Sets a mark on this stream.
 boolean markSupported()
          This class supports mark and reset only if all reader in this class support it, too.
 int read(char[] buffer, int offset, int length)
          Reads characters from one of the underlying readers.
 boolean ready()
          Tells whether this stream is ready to be read.
 void reset()
          Sets back the list of readers to the most recent mark.
 int size()
          Returns the amount of readers combined in this MultiFileReader .
 long skip(long n)
          Skip characters.
static java.lang.String testFilenames(java.lang.String names)
          Tests the filenames to be existing files.
 java.lang.String toString()
          Prints the quoted filenames seperated by comma.
 
Methods inherited from class java.io.Reader
read, read, read
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

readers

private java.util.Vector readers
The storage container of the subsequent readers.


filenames

private java.util.Vector filenames
The storage container of the readers filenames. A null name in here stands for either the delimiter string or a reader added through the add( Reader ) method.

See Also:
add(Reader)

actualReader

private int actualReader
The actual position in the readers vector.


markedReader

private int markedReader
The reader marked. If the value is greater or equal one it is meant to be an index in the readers vector. A value of -1 means that no mark is set yet.


actReader

private java.io.Reader actReader
The reader actually used for read and write operations. This is stored for faster redirection processes.


readerDelimiter

private java.lang.String readerDelimiter
The string used as a delimiter between the different reader in readers.


markSupported

private boolean markSupported
Changed when adding Readers through one of the add-methods. Stays true if all added reader support mark and reset methods.

Constructor Detail

MultiFileReader

public MultiFileReader(java.lang.String delimiter)
Constructs a new MultiFileReader object with the given reader delimiter.

Parameters:
delimiter - The delimiter read between the different reader. May be null.
Method Detail

add

public void add(java.lang.String filename)
         throws java.io.FileNotFoundException,
                java.lang.NullPointerException
Adds a new ResetableReader to the vector of subsequence readers.

Parameters:
filename - The filename of the file to open.
Throws:
java.io.FileNotFoundException - If the file could not be found.
java.lang.NullPointerException - If filename is null.

add

public void add(java.io.Reader reader)
         throws java.lang.NullPointerException
Adds a Reader to the underlying storage container. Make sure the reader supports the mark() and reset() operations properly. And further make sure, that the reader works like a ResetableReader the way, that two subsequent resets set back the reader to the beginning and not to the mark.

Parameters:
reader - The reader to add.
Throws:
java.lang.NullPointerException - If reader is null.

close

public void close()
Closes and disbands all Readers stored in this class. Does not throw any exceptions. After calling this method you must not try to add new readers to this class or call any other method.

Specified by:
close in interface java.io.Closeable
Specified by:
close in class java.io.Reader

size

public int size()
Returns the amount of readers combined in this MultiFileReader . If no delimiter was given, the size is the number of readers added previously, otherwise the size is (2 x #addedReader - 1).

Returns:
The number of readers combined in this class.

get

public java.io.Reader get(int index)
                   throws java.lang.IndexOutOfBoundsException
Returns a reader for a given index. Note, that the readers returned do reflect the order as they are added only if no delimiter was given, otherwise the delimiter is returned every second index.

Parameters:
index - Points at the reader to return.
Returns:
The reader for the given index.
Throws:
java.lang.IndexOutOfBoundsException - If index is less than zero or greater or equal to size().
See Also:
size()

getFilename

public java.lang.String getFilename(int index)
                             throws java.lang.IndexOutOfBoundsException
Returns the filename for a given index. If null is returned the corresponding reader is either the delimiter or was added through the add( Reader ) method without providing a filename. If the delimiter string was set when this class was constructed, every second index null is returned.

Parameters:
index - Index of the reader whoms filename is to return.
Returns:
The filename for a given index or null in some cases.
Throws:
java.lang.IndexOutOfBoundsException - If index is less than zero or greater or equal to size().
See Also:
size()

read

public int read(char[] buffer,
                int offset,
                int length)
         throws java.io.IOException
Reads characters from one of the underlying readers. If the end of one reader is reached, the next is opened and the buffer is filled.

Specified by:
read in class java.io.Reader
Parameters:
buffer - The buffer to write to.
offset - The start of the buffer.
length - Number of characters to read maximal.
Returns:
The number of valid characters written into the buffer. -1 is returned if no character could be read due to a EOF.
Throws:
java.io.IOException - From the underlying Reader, e.g. if the file could not be found anymore.

markSupported

public boolean markSupported()
This class supports mark and reset only if all reader in this class support it, too. Setting a mark works by remembering the actual reader and redirecting the mark() to that reader. After a reset all Reader after the marked one are re-set and the marked one got the reset attempt. If only one underlying reader does not support mark and reset, it is skipped for the whole class.

Overrides:
markSupported in class java.io.Reader
Returns:
true iff all underlying readers return true by this method, false otherwise.

mark

public void mark(int readAheadLimit)
          throws java.io.IOException
Sets a mark on this stream. After performing a reset() it is garantied, that the next readable character is the one a read would now return.
The parameter is forwarded without change to the underlying Reader.

Overrides:
mark in class java.io.Reader
Parameters:
readAheadLimit - The number of characters to read until the mark on the stream expires.
Throws:
java.io.IOException - If the actual reader does not support mark and reset.
See Also:
ResetableReader.mark(int)

reset

public void reset()
           throws java.io.IOException
Sets back the list of readers to the most recent mark. First, all readers read after the marked one are reset to the beginning. Then the marked reader is reset.

Overrides:
reset in class java.io.Reader
Throws:
java.io.IOException - If the file could not be reopened, or if the reopened stream could not be read to the mark.
See Also:
ResetableReader.reset()

skip

public long skip(long n)
          throws java.io.IOException
Skip characters. The reads are preformed through the read(char[], int, int)-method.

Overrides:
skip in class java.io.Reader
Parameters:
n - The number of characters to skip
Returns:
The number of characters actually skipped.
Throws:
java.io.IOException - If an I/O error occurs.

ready

public boolean ready()
              throws java.io.IOException
Tells whether this stream is ready to be read. This call is simple forwarded to the underlying Reader

Overrides:
ready in class java.io.Reader
Returns:
true if the next read() is guaranteed not to block for input, false otherwise. Note that returning false does not guarantee that the next read will block.
Throws:
java.io.IOException - If an I/O error occurs

toString

public java.lang.String toString()
Prints the quoted filenames seperated by comma.

Overrides:
toString in class java.lang.Object

testFilenames

public static java.lang.String testFilenames(java.lang.String names)
Tests the filenames to be existing files. The string names might contain one or more quoted filenames, seperated by comma (e.g. '"/homes/a", "/digit", "/homes/a+b"'). From every filename a File-object is created and, if isFile() returned true it is included in the returned list, otherwise discarded.

Parameters:
names - An collection of filenames.
Returns:
A String containing the filenames, for which the corresponding file exists.
See Also:
add(String), toString(), File.isFile()

filesToString

public static java.lang.String filesToString(java.io.File[] files)
Joins the filenames of all given Files into one string. The convention is, that each filename is double-quoted, and two filenames are seperated with ", " (comma space). If a file is null, it is ignored. if files is null the empty String is returned.

Parameters:
files - A number of Files whos names are to be concatenated.
Returns:
A String of concatenated, comma-delimited, double-quoted filenames.

getReader

public static java.io.Reader getReader(java.lang.String names)
                                throws java.io.FileNotFoundException,
                                       java.lang.NullPointerException
Creates either a MultiFileReader or a ResetableReader from the filenames comprised in names. If only one filename is given one ResetableReader is returned. Multiple filenames in names must be double-quoted and delimited by ", " (comma space).

Parameters:
names - The filenames to be concatenated.
Returns:
Either a MultiFileReader or a ResetableReader.
Throws:
java.io.FileNotFoundException - If a file was not found.
java.lang.NullPointerException - If a names is null.