/*- * Copyright © 2009 Diamond Light Source Ltd. * * This file is part of GDA. * * GDA is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License version 3 as published by the Free * Software Foundation. * * GDA is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along * with GDA. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.gda.util.io; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * Read a tabbed delimited file into columns. Each row must have * the same number of entries currently. * * Assumes that files are small. For larger files use StreamTokenizer(Reader r) which is more efficient. */ public class TokenFileParser { private String token = "\\t"; private String commentChar = "#"; private List<List<String>> data; private BufferedReader reader; /** * @param url * @throws IOException */ public TokenFileParser(final URL url) throws IOException { this(url.openStream()); } /** * @param file * @throws IOException */ public TokenFileParser(final File file) throws IOException { this(new FileInputStream(file)); } /** * NOTE Does not use StreamTokenizer so files need to be small. * * @param unbuffered * @throws IOException */ public TokenFileParser(final InputStream unbuffered) throws IOException { this.data = new ArrayList<List<String>>(7); this.reader = new BufferedReader(new InputStreamReader(unbuffered, "US-ASCII")); } /** * Must be called to parse the file. * @throws IOException */ public void parse() throws IOException { boolean firstLine = true; String l = null; while((l=reader.readLine())!=null) { if (getCommentChar()!=null && l.startsWith(getCommentChar())) continue; final String[] line = l.trim().split(token); int index = 0; for (int i = 0; i < line.length; i++) { final String value = line[i].trim(); if ("".equals(value)) continue; if (firstLine) data.add(new ArrayList<String>(31)); final List<String> d = data.get(index); d.add(value); ++index; } firstLine = false; } } /** * @param icol * @return the exact column, modifying it will change the data */ public List<String> getColumn(final int icol) { return data.get(icol); } @Override public String toString() { final StringBuilder buf = new StringBuilder(); final int size = data.get(0).size(); for (int i = 0; i < size; i++) { for (List<String> d : data) { buf.append("\t"); buf.append(d.get(i)); } buf.append("\n"); } return buf.toString(); } /** * Exceptions can be thrown if the column cannot parse as double * @param i * @return Double[] */ public Double[] getColumnAsDoubleArray(int i, int... ignoreRows) { final List<Double> ret = getColumnAsDoubleList(i, ignoreRows); return ret.toArray(new Double[ret.size()]); } /** * @param i * @param ignoreRows * @return column as list of Doubles */ public List<Double> getColumnAsDoubleList(int i, int... ignoreRows) { final List<Integer> ig = new ArrayList<Integer>(ignoreRows.length); for (int j = 0; j < ignoreRows.length; j++) ig.add(ignoreRows[j]); final List<String> values = data.get(i); final List<Double> ret = new ArrayList<Double>(values.size()); for (int row = 0; row < values.size(); row++) { if (ig.contains(row)) continue; ret.add(Double.valueOf(values.get(row))); } return ret; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public String getCommentChar() { return commentChar; } public void setCommentChar(String commentChar) { this.commentChar = commentChar; } }