/* XBN Java: Generically useful, non-GUI Java code. http://sourceforge.net/projects/xbnjava Copyright (C) 1997-2003, Jeff Epstein All rights reserved. Modifications: No Redistribution in binary form, with or without modifications, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * If modifications are made to source code then this license should indicate that fact in the "Modifications" section above. * Neither the author, nor the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [NOTE: This license contains NO advertising clause.] */ package xbn.util; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /**

A ForLineRetrieval where the source text comes from a text File.

Source code:  FLRFile.java

@version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava. **/ public class FLRFile extends ForLineRetrieval { private FileInputStream fis = null; private String sFileName = null; private StringBuffer sbPrevLineRetrieved = null; private int iLSIdx = 0; /**

Create a FLRFile.

@param s_fileName The relative or full path and file name, representing a file that contains source text. This file must exist and be readable. **/ public FLRFile(String s_fileName) { this(null, s_fileName); } /**

Create a FLRFile.

@param s_lineSep This parameter is ignored. Note that the super constructor is called with "x", but this is only to avoid an exception being thrown from the constructor. Is there any way to tell fis.read() to consider something else as the line separator? **/ private FLRFile(String s_lineSep, String s_fileName) { super("x"); throwAXIfBadStr(s_fileName, "s_fileName", sCNSTR); try { fis = new FileInputStream(s_fileName); sFileName = s_fileName; } catch(FileNotFoundException fnfx) { closeFileInputStream(); throwAX("constructor: " + fnfx.toString()); } //Get the first line. Initialize sbPrevLineRetrieved to //empty string to avoid an AssertException. getNextLine(true); } /**

Get the next line from the file, including the ending new line ("\\n"). If all lines have been retrieved (if hasMoreLines equals false), then return null.

**/ public StringBuffer getNextLine() { return getNextLine(false); } private StringBuffer getNextLine(boolean b_calledByConstructor) { if(!b_calledByConstructor && !hasMoreLines()) { throwAX("getNextLine: No more lines to retrieve. hasMoreLines has returned false."); } StringBuffer sbLineToReturn = sbPrevLineRetrieved; sbPrevLineRetrieved = null; if(!hasMoreLines()) { //The only way we'll reach this point is if the //*previous* line retrieval was the last. incLineNumber(); return sbLineToReturn; } sbPrevLineRetrieved = new StringBuffer(sES); try { String sChar = null; byte[] ab = new byte[1]; while(true) { int iStatus = fis.read(ab); if(iStatus == -1) { //The (previous) character read in was the final //character in this file. closeFileInputStream(); if(!b_calledByConstructor) { //The first call to this function reads the //first line from the file. This is always //from the constructor. The second call (and //all subsequent) are called from external //code. They the *next* line is read from //the file, and the *previous* line is //returned to them. // //Moral: When the constructor calls this //function, leave it as its initial value: 1. //Only the second and subsequent calls to this //function should inc the line number. incLineNumber(); } return sbLineToReturn; } //We've just read in another character. This may //be the last character, or any one before it. sChar = new String(ab); sbPrevLineRetrieved.append(sChar); if(iLSIdx < sLINE_SEP.length()) { //Is the just-read character the X-th in a line //separator? if(sChar.charAt(0) == sLINE_SEP.charAt(iLSIdx++)) { //It is. if(iLSIdx == sLINE_SEP.length()) { //A full line separator was found. Hooray. //It is the end of this line. iLSIdx = 0; if(!b_calledByConstructor) { incLineNumber(); } return sbLineToReturn; } //ELSE: There are more line-separator chars to // find. But so far, so good. } else { //This is not the X-th in a line separator. //Start the search over again with the next- //read-in character. iLSIdx = 0; } } } } catch(IOException iox) { closeFileInputStream(); throwAX("getNextLine: " + iox.toString()); } //Never reached. Required for compile. return null; } /**

Are there any more lines to retrieved?

@return true If there is at least one more line to be retrieved by getNextLine.
false If there are no more lines left to retrieve. **/ public boolean hasMoreLines() { return (fis != null || sbPrevLineRetrieved != null); } /**

Get the file name. This file name is exactly as provided to this class' constructor.

**/ public String getFileName() { return sFileName; } private void closeFileInputStream() { IOException iox = null; try { if(fis != null) { fis.close(); } } catch(IOException iox2) { iox = iox2; } finally { fis = null; if(iox != null) { throwAX(". Attempting to close the FileInputStream: " + iox.toString()); } } } /**

Get some information about this FLRFile.

**/ public final String toString() { return this.getClass().getName() + ": getFileName()='" + getFileName() + "'"; } /**

When this OWFile object is destroyed, this properly closes the FileInputStream.

**/ protected void finalize() throws Throwable { closeFileInputStream(); super.finalize(); } }