package statalign.io.input;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
* Class that allows reading the contents of a file token by token, without worrying about
* line ends and whitespace. E.g. files containing ten integers in a single line or ten
* lines can be handled in a uniform way. Inspired by the C call fscanf(file, "%d", &value).
*
* Tokens can be integers, doubles or strings. Separators are any combination of whitespace
* characters as recognized by the regular expression \s+ .
*
* @author novak
*
*/
public class FileTokenReader {
private BufferedReader file;
private String tokens[];
private int ind;
boolean EOF;
/**
* Constructs a FileTokenReader reading a given file.
*
* @param fname Name of the file to read
* @throws IOException if an I/O error occurs
*/
public FileTokenReader(String fname) throws IOException {
ClassLoader cl = getClass().getClassLoader();
file = new BufferedReader(new InputStreamReader(cl.getResource(fname).openStream()));
// file = new BufferedReader(new FileReader(fname));
tokens = null;
ind = 0;
EOF = false;
}
protected boolean readTokens() throws IOException {
String line;
while(tokens == null || ind == tokens.length || tokens[ind].length() == 0) {
if((line = file.readLine()) == null) {
EOF = true;
return false;
}
tokens = line.split("\\s+");
ind = 0;
}
return true;
}
/**
* Reads the next token and tries to interpret it as a double value.
*
* @return Double value of the token or null if end of file has been reached
* @throws IOException if an I/O error occurs
* @throws NumberFormatException if next token cannot be converted to Double
*/
public Double readDbl() throws IOException {
return readTokens()?Double.valueOf(tokens[ind++]):null;
}
/**
* Reads the next token and tries to interpret it as an integer value.
*
* @return Integer value of the token or null if end of file has been reached
* @throws IOException if an I/O error occurs
* @throws NumberFormatException if next token cannot be converted to Integer
*/
public Integer readInt() throws IOException {
return readTokens()?Integer.valueOf(tokens[ind++]):null;
}
/**
* Reads the next token and returns it as a String.
*
* @return Next token as String or null if end of file has been reached
* @throws IOException if an I/O error occurs
*/
public String readStr() throws IOException {
return readTokens()?tokens[ind++]:null;
}
/**
* Closes the underlying file.
*
* @throws IOException if an I/O error occurs
*/
public void close() throws IOException {
file.close();
}
}