package umontreal.iro.lecuyer.util;
import java.io.LineNumberReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.logging.Logger;
/**
* Provides static methods to read data from text files.
*
*/
public class TextDataReader {
private static Logger log = Logger.getLogger ("umontreal.iro.lecuyer.util");
/**
* Reads an array of double-precision values from the
* reader input.
* For each line of text obtained from the
* given reader, this method
* trims whitespaces, and parses the
* remaining text as a double-precision value.
* This method ignores every character
* other than the digits, the plus and minus signs,
* the period (.),
* and the letters e and E.
* Moreover, lines starting with a pound sign (#)
* are considered as comments and thus skipped.
* The method returns an array containing
* all the parsed values.
*
* @param input the reader to obtain data from.
*
* @return the obtained array of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[] readDoubleData (Reader input) throws IOException {
LineNumberReader inb = new LineNumberReader (input);
double[] data = new double[5];
int n = 0;
String li;
while ((li = inb.readLine()) != null) {
li = li.trim();
if (li.startsWith ("#"))
continue;
// look for the first non-digit character on the read line
int index = 0;
while (index < li.length() &&
(li.charAt (index) == '+' || li.charAt (index) == '-' ||
li.charAt (index) == 'e' || li.charAt (index) == 'E' ||
li.charAt (index) == '.' || Character.isDigit (li.charAt (index))))
++index;
// truncate the line
li = li.substring (0, index);
if (!li.equals ("")) {
try {
data[n++] = Double.parseDouble (li);
if (n >= data.length) {
double[] newData = new double[2*n];
System.arraycopy (data, 0, newData, 0, data.length);
data = newData;
}
}
catch (NumberFormatException nfe) {
log.warning ("Invalid line " + inb.getLineNumber() + ": " + li);
}
}
}
if (data.length != n) {
double[] data2 = new double[n];
System.arraycopy (data, 0, data2, 0, n);
return data2;
}
return data;
}
/**
* Connects to the URL referred to by the URL object url,
* and calls {@link #readDoubleData((Reader)) readDoubleData} to
* obtain an array of double-precision values from
* the resource.
*
* @param url the URL object representing the resource to read.
*
* @return the obtained array of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[] readDoubleData (URL url) throws IOException {
Reader reader = new InputStreamReader (url.openStream());
try {
return readDoubleData (reader);
}
finally {
reader.close();
}
}
/**
* Opens the file referred to by the file object file,
* and calls {@link #readDoubleData((Reader)) readDoubleData} to
* obtain an array of double-precision values from
* the file.
*
* @param file the file object representing the file to read.
*
* @return the obtained array of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[] readDoubleData (File file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readDoubleData (reader);
}
finally {
reader.close();
}
}
/**
* Opens the file with name file,
* and calls {@link #readDoubleData((Reader)) readDoubleData} to
* obtain an array of double-precision values from
* the file.
*
* @param file the name of the file to read.
*
* @return the obtained array of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[] readDoubleData (String file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readDoubleData (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData((Reader)) readDoubleData},
* for reading integers.
*
* @param input the reader to obtain data from.
*
* @return the obtained array of integers.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[] readIntData (Reader input) throws IOException {
LineNumberReader inb = new LineNumberReader (input);
int[] data = new int[5];
int n = 0;
String li;
while ((li = inb.readLine()) != null) {
li = li.trim();
if (li.startsWith ("#"))
continue;
// look for the first non-digit character on the read line
int index = 0;
while (index < li.length() &&
(li.charAt (index) == '+' || li.charAt (index) == '-' ||
Character.isDigit (li.charAt (index))))
++index;
// truncate the line
li = li.substring (0, index);
if (!li.equals ("")) {
try {
data[n++] = Integer.parseInt (li);
if (n >= data.length) {
int[] newData = new int[2*n];
System.arraycopy (data, 0, newData, 0, data.length);
data = newData;
}
}
catch (NumberFormatException nfe) {
log.warning ("Invalid line " + inb.getLineNumber() + ": " + li);
}
}
}
if (data.length != n) {
int[] data2 = new int[n];
System.arraycopy (data, 0, data2, 0, n);
return data2;
}
return data;
}
/**
* Connects to the URL referred to by the URL object url,
* and calls {@link #readIntData((Reader)) readIntData} to
* obtain an array of integers from
* the resource.
*
* @param url the URL object representing the resource to read.
*
* @return the obtained array of integers.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[] readIntData (URL url) throws IOException {
Reader reader = new InputStreamReader (url.openStream());
try {
return readIntData (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData((File)) readDoubleData},
* for reading integers.
*
* @param file the file object represented to file to read.
*
* @return the array of integers.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[] readIntData (File file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readIntData (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData((String)) readDoubleData},
* for reading integers.
*
* @param file the name of the file to read.
*
* @return the array of integers.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[] readIntData (String file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readIntData (reader);
}
finally {
reader.close();
}
}
/**
* Reads an array of strings from the
* reader input.
* For each line of text obtained from the
* given reader, this method
* trims leading and trailing whitespaces, and stores the remaining string.
* Lines starting with a pound sign (#)
* are considered as comments and thus skipped.
* The method returns an array containing
* all the read strings.
*
* @param input the reader to obtain data from.
*
* @return the obtained array of strings.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[] readStringData (Reader input) throws IOException {
LineNumberReader inb = new LineNumberReader (input);
String[] data = new String[5];
int n = 0;
String li;
while ((li = inb.readLine()) != null) {
li = li.trim();
if (li.startsWith ("#"))
continue;
data[n++] = li;
if (n >= data.length) {
String[] newData = new String[2*n];
System.arraycopy (data, 0, newData, 0, data.length);
data = newData;
}
}
if (data.length != n) {
String[] data2 = new String[n];
System.arraycopy (data, 0, data2, 0, n);
return data2;
}
return data;
}
/**
* Connects to the URL referred to by the URL object url,
* and calls {@link #readStringData((Reader)) readStringData} to
* obtain an array of integers from
* the resource.
*
* @param url the URL object representing the resource to read.
*
* @return the obtained array of strings.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[] readStringData (URL url) throws IOException {
Reader reader = new InputStreamReader (url.openStream());
try {
return readStringData (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData((File)) readDoubleData},
* for reading strings.
*
* @param file the file object represented to file to read.
*
* @return the array of strings.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[] readStringData (File file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readStringData (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData((String)) readDoubleData},
* for reading strings.
*
* @param file the name of the file to read.
*
* @return the array of strings.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[] readStringData (String file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readStringData (reader);
}
finally {
reader.close();
}
}
/**
* Uses the reader input to obtain
* a 2-dimensional array of double-precision values.
* For each line of text obtained from the
* given reader, this method
* trims whitespaces, and parses the
* remaining text as an array of double-precision values.
* Every character
* other than the digits, the plus (+) and minus (-) signs,
* the period (.),
* and the letters e and E are
* ignored and can be used to separate
* numbers on a line.
* Moreover, lines starting with a pound sign (#)
* are considered as comments and thus skipped. The lines
* containing only a semicolon sign (;) are considered
* as empty lines.
* The method returns a 2D array containing
* all the parsed values.
* The returned array is not always rectangular.
*
* @param input the reader to obtain data from.
*
* @return the 2D array of double-precison values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[][] readDoubleData2D (Reader input)
throws IOException {
LineNumberReader inb = new LineNumberReader (input);
double[][] data = new double[5][];
int n = 0;
String li;
String number;
while ((li = inb.readLine()) != null) {
li = li.trim();
if (li.startsWith ("#"))
continue;
if (li.equals(";")) {
data[n++] = new double[0];
}
else {
int index = 0;
int begin = 0;
boolean end = false;
double[] row = new double[5];
int k = 0;
while (index < li.length() && (! end))
{
while (index < li.length() &&
(li.charAt (index) == '+' || li.charAt (index) == '-' ||
li.charAt (index) == 'e' || li.charAt (index) == 'E' ||
li.charAt (index) == '.' || Character.isDigit (li.charAt (index))))
++index;
if (index >= li.length() || (Character.isWhitespace (li.charAt (index))))
{
number = li.substring (begin, index);
begin = ++index;
if (! number.equals("")) {
try {
row[k++] = Double.parseDouble (number);
if (k >= row.length) {
double[] newRow = new double[2*k];
System.arraycopy (row, 0, newRow, 0, row.length);
row = newRow;
}
}
catch (NumberFormatException nfe) {
log.warning ("Invalid column " + k + " at line " + inb.getLineNumber() + ": " + number);
}
}
}
else {
end = true;
}
}
if (k > 0) {
data[n] = new double[k];
System.arraycopy (row, 0, data[n], 0, k);
n++;
}
else {
log.warning ("Invalid line " + inb.getLineNumber() + ": " + li);
}
}
if (n == data.length) {
double[][] newData = new double[2*n][];
System.arraycopy (data, 0, newData, 0, n);
data = newData;
}
}
double[][] data2 = new double[n][];
System.arraycopy (data, 0, data2, 0, n);
return data2;
}
/**
* Connects to the URL referred to by the URL object url,
* and calls {@link #readDoubleData2D((Reader)) readDoubleData2D} to
* obtain a matrix of double-precision values from
* the resource.
*
* @param url the URL object representing the resource to read.
*
* @return the obtained matrix of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[][] readDoubleData2D (URL url) throws IOException {
Reader reader = new InputStreamReader (url.openStream());
try {
return readDoubleData2D (reader);
}
finally {
reader.close();
}
}
/**
* Opens the file referred to by the file object file,
* and calls {@link #readDoubleData2D((Reader)) readDoubleData2D} to
* obtain a matrix of double-precision values from
* the file.
*
* @param file the file object representing the file to read.
*
* @return the obtained matrix of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[][] readDoubleData2D (File file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readDoubleData2D (reader);
}
finally {
reader.close();
}
}
/**
* Opens the file with name file,
* and calls {@link #readDoubleData2D((Reader)) readDoubleData2D} to
* obtain a matrix of double-precision values from
* the file.
*
* @param file the name of the file to read.
*
* @return the obtained matrix of double-precision values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static double[][] readDoubleData2D (String file)
throws IOException {
FileReader reader = new FileReader (file);
try {
return readDoubleData2D (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData2D((Reader)) readDoubleData2D},
* for reading integers.
*
* @param input the reader to obtain data from.
*
* @return the obtained 2D array of integers.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[][] readIntData2D (Reader input) throws IOException {
LineNumberReader inb = new LineNumberReader (input);
int[][] data = new int[5][];
int n = 0;
String li;
String number;
while ((li = inb.readLine()) != null) {
li = li.trim();
if (li.startsWith ("#"))
continue;
if (li.equals(";")) {
data[n++] = new int[0];
}
else {
int index = 0;
int begin = 0;
boolean end = false;
int[] row = new int[5];
int k = 0;
while (index < li.length() && (! end))
{
while (index < li.length() &&
(li.charAt (index) == '+' || li.charAt (index) == '-' ||
Character.isDigit (li.charAt (index))))
++index;
if (index >= li.length() || (Character.isWhitespace (li.charAt (index))))
{
number = li.substring (begin, index);
begin = ++index;
if (! number.equals("")) {
try {
row[k++] = Integer.parseInt (number);
if (k >= row.length) {
int[] newRow = new int[2*k];
System.arraycopy (row, 0, newRow, 0, row.length);
row = newRow;
}
}
catch (NumberFormatException nfe) {
log.warning ("Invalid column " + k + " at line " + inb.getLineNumber() + ": " + number);
}
}
}
else {
end = true;
}
}
if (k > 0) {
data[n] = new int[k];
System.arraycopy (row, 0, data[n], 0, k);
n++;
}
else {
log.warning ("Invalid line " + inb.getLineNumber() + ": " + li);
}
}
if (n == data.length) {
int[][] newData = new int[2*n][];
System.arraycopy (data, 0, newData, 0, n);
data = newData;
}
}
int[][] data2 = new int[n][];
System.arraycopy (data, 0, data2, 0, n);
return data2;
}
/**
* Connects to the URL referred to by the URL object url,
* and calls {@link #readDoubleData((Reader)) readDoubleData} to
* obtain a matrix of integers from
* the resource.
*
* @param url the URL object representing the resource to read.
*
* @return the obtained matrix of integers.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[][] readIntData2D (URL url) throws IOException {
Reader reader = new InputStreamReader (url.openStream());
try {
return readIntData2D (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData2D((File)) readDoubleData2D},
* for reading integers.
*
* @param file the file object represented to file to read.
*
* @return the obtained matrix of integer values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[][] readIntData2D (File file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readIntData2D (reader);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData2D((String)) readDoubleData2D},
* for reading integers.
*
* @param file the name of the file to read.
*
* @return the obtained matrix of integer values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static int[][] readIntData2D (String file) throws IOException {
FileReader reader = new FileReader (file);
try {
return readIntData2D (reader);
}
finally {
reader.close();
}
}
/**
* Reads comma-separated values (CSV) from reader input, and
* returns a 2D array of strings corresponding to the read data.
* Lines are delimited using line separators r,
* n, and rn.
* Each line contains one or more values, separated by the column
* delimiter colDelim.
* If a string of characters is surrounded with the string delimiter
* stringDelim, any line separator and column separator appear in
* the string. The string delimiter can be inserted in such a string by
* putting it twice.
* Usually, the column delimiter is the comma, and the string delimiter is
* the quotation mark. The following example uses these default
* delimiters.
*
* "One","Two","Three"
* 1,2,3
* "String with "" delimiter",n,m
*
* This produces a matrix of strings with dimensions 3×3.
* The first row contains the strings One, Two, and Three
* while the second row contains the strings 1, 2, and 3.
* The first column of the last row contains the string
* String with " delimiter.
*
* @param input the reader to obtain data from.
*
* @param colDelim the column delimiter.
*
* @param stringDelim the string delimiter.
*
* @return the obtained 2D array of strings.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[][] readCSVData (Reader input, char colDelim,
char stringDelim)
throws IOException {
// Using a buffered reader is important here for performance
// LineNumberReader is a subclass of BufferedReader
LineNumberReader inb = new LineNumberReader (input);
StringBuffer sb = new StringBuffer();
boolean stringMode = false;
String[][] data = new String[5][];
int numRows = 0;
int numColumns = 0;
boolean newRow = false, newColumn = false;
int ich = -1;
char ch = ' ';
boolean readDone = false;
while (!readDone) {
if (ich == -2)
// A character is pending
ich = 0;
else {
ich = inb.read();
if (ich == -1)
// End of stream: process the last column and row, and exit
newRow = newColumn = readDone = true;
else
ch = (char)ich;
}
if (ich != -1) {
if (stringMode) {
if (ch == stringDelim) {
// Check if there is a second string delimiter
int ichNext = inb.read();
if (ichNext >= 0) {
char chNext = (char)ichNext;
if (chNext == stringDelim)
// Append the quoted string delimiter
sb.append (stringDelim);
else {
// Indicate the end of the string, and a new pending character
stringMode = false;
ich = -2;
ch = chNext;
}
}
}
else
sb.append (ch);
}
else {
if (ch == '\n' || ch == '\r') {
int ichNext = inb.read();
if (ichNext >= 0) {
char chNext = (char)ichNext;
if (ch == '\r' && chNext == '\n') {
ichNext = inb.read();
if (ichNext >= 0) {
chNext = (char)ichNext;
ich = -2;
ch = chNext;
newRow = true;
}
}
else {
ich = -2;
ch = chNext;
newRow = true;
}
}
}
else if (ch == colDelim)
newColumn = true;
else if (ch == stringDelim)
stringMode = true;
else
sb.append (ch);
}
}
if (newColumn || newRow) {
if (numColumns == 0) {
++numRows;
numColumns = 1;
}
else
++numColumns;
if (data.length < numRows) {
String[][] newData = new String[2*data.length][];
System.arraycopy (data, 0, newData, 0, data.length);
data = newData;
}
if (data[numRows - 1] == null)
data[numRows - 1] = new String[5];
else if (data[numRows - 1].length < numColumns) {
String[] newData = new String[2*data[numRows - 1].length];
System.arraycopy (data[numRows - 1], 0, newData, 0, data[numRows - 1].length);
data[numRows - 1] = newData;
}
data[numRows - 1][numColumns - 1] = sb.toString();
sb.delete (0, sb.length());
newColumn = false;
}
if (newRow) {
if (data[numRows - 1].length != numColumns) {
String[] data2 = new String[numColumns];
System.arraycopy (data[numRows - 1], 0, data2, 0, numColumns);
data[numRows - 1] = data2;
}
numColumns = 0;
newRow = false;
}
}
if (stringMode)
throw new IllegalArgumentException ("Too many string delimiters " + stringDelim);
if (data.length != numRows) {
String[][] data2 = new String[numRows][];
System.arraycopy (data, 0, data2, 0, numRows);
return data2;
}
return data;
}
/**
* Connects to the URL referred to by the URL object url,
* and calls {@link #readCSVData((Reader,char,char)) readCSVData} to
* obtain a matrix of strings from
* the resource.
*
* @param url the URL object representing the resource to read.
*
* @param colDelim the column delimiter.
*
* @param stringDelim the string delimiter.
*
* @return the obtained matrix of strings.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[][] readCSVData (URL url, char colDelim,
char stringDelim)
throws IOException {
Reader reader = new InputStreamReader (url.openStream());
try {
return readCSVData (reader, colDelim, stringDelim);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData2D((File)) readDoubleData2D},
* for reading strings.
*
* @param file the file object represented to file to read.
*
* @param colDelim the column delimiter.
*
* @param stringDelim the string delimiter.
*
* @return the obtained matrix of string values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[][] readCSVData (File file, char colDelim,
char stringDelim)
throws IOException {
FileReader reader = new FileReader (file);
try {
return readCSVData (reader, colDelim, stringDelim);
}
finally {
reader.close();
}
}
/**
* This is equivalent to {@link #readDoubleData2D((String)) readDoubleData2D},
* for reading strings.
*
* @param file the name of the file to read.
*
* @param colDelim the column delimiter.
*
* @param stringDelim the string delimiter.
*
* @return the obtained matrix of string values.
* @exception IOException if an I/O error occurs.
*
*
*/
public static String[][] readCSVData (String file, char colDelim,
char stringDelim)
throws IOException {
FileReader reader = new FileReader (file);
try {
return readCSVData (reader, colDelim, stringDelim);
}
finally {
reader.close();
}
}
}
Ads help maintain this website.