View Javadoc

1   package org.astrogrid.io.ascii;
2   
3   
4   /***
5    * An InputStream that provides a set of convenience routines for reading from
6    * an ASCII file.  Such files may be separated by some character (often a comma
7    * for comma-separated variables) or may be arranged in columns.  This stream
8    * provides methods for reading type-specific variables (eg, Integers, Strings,
9    * Booleans, etc) from both.
10   * Creation date: Jan 2001
11   * @author: M Hill
12   */
13  
14  import java.io.*;
15  import org.astrogrid.io.ascii.AsciiCodes;
16  
17  public class AsciiInputStream extends FilterInputStream
18  {
19      public static int c_eoLine = AsciiCodes.LF;
20      public static int c_eoFile = -1;
21      private char defaultEoField = ',';
22      private boolean isEOL = false;
23      private boolean checkForEOLine = true;
24      
25      /***
26       * Constructor - pass in the stream that it should read from
27       */
28      public AsciiInputStream(java.io.InputStream in) {
29          super(in);
30      }
31  
32      /***
33       * Private method used to see if the given character is an end of line
34       * marker (ie, a line feed) or indicates the end of file when no more
35       * characters are available
36       * @return boolean true if given character is end of line
37       * @param c int
38       */
39      private boolean charIsEOLine(int c) {
40          if (checkForEOLine)
41              return ((c == c_eoLine) || (c == c_eoFile));
42          else
43              return false;
44      }
45  
46      /***
47       * Returns true if the end of line marker is set
48       */
49      public boolean isEOLine() {
50          return isEOL;
51      }
52  
53      /***
54       * Sets the eoField character
55       */
56      public void setEoField(char newEoFieldMarker)
57      {
58          defaultEoField = newEoFieldMarker;
59      }
60      
61      /***
62       * Returns true/false if it thinks the given string indicates true/false,
63       * or throws exception if it can't tell
64       */
65      private boolean isFieldBoolean(String field) throws IOException
66      {
67          String firstChar = field.substring(0,0);
68          
69          if (firstChar.equalsIgnoreCase("Y") || firstChar.equalsIgnoreCase("T")) //yes or true
70              return true;
71          
72          if (firstChar.equalsIgnoreCase("N") || firstChar.equalsIgnoreCase("F")) //yes or true
73              return false;
74  
75          throw new IOException("Cannot resolve "+field+" to boolean");
76      }
77      
78      /***
79       * Reads up to next defaultEoField character and returns whether it thinks
80       * that field indicates true or false.
81       * @see isFieldBoolean
82       */
83      public boolean readBoolean() throws IOException
84      {
85          return isFieldBoolean(readString().trim());
86      }
87      
88      /***
89       * Reads up to the next occurence of the given character, and returns whether
90       * it thinks that field indicates true or false
91       * @see isFieldBoolean
92       */
93      public boolean readBoolean(char eoField) throws IOException
94      {
95          return isFieldBoolean(readString(eoField).trim());
96      }
97  
98      /***
99       * Reads up to the next defaultEoField character and returns a long
100      * representation of it
101      */
102     public long readNum() throws IOException {
103         return readNum(defaultEoField);
104     }
105 
106     /***
107      * Reads an integer from the ASCII stream, by reading a string until
108      * the given end-of-field marker and then converting it to an integer.
109      * @return int
110      */
111     public long readNum(char eoField) throws IOException {
112         
113         //read string of given width
114         //trim cuts spaces and all chars less than a space (eg cr/lf)
115         String numString = readString(eoField).trim();
116         
117         if (numString.length() == 0)
118             return 0;
119         
120         //convert to integer object...
121         Long numLong = new Long(numString);
122         
123         //,,,so that we can convert that to an int.
124         return numLong.longValue();
125     }
126 
127     /***
128      * Reads an integer from the ASCII stream, by reading a string of the
129      * given length (ie, column width) and then converting it to an integer.
130      */
131     public long readNum(int width) throws IOException {
132         
133         //read string of given width
134         //trim cuts spaces and all chars less than a space (eg cr/lf)
135         String numString = readString(width).trim();
136         
137         if (numString.length() == 0)
138             return 0;
139         
140         //convert to integer object...
141         Long numLong = new Long(numString);
142         
143         //,,,so that we can convert that to an int.
144         return numLong.longValue();
145     }
146 
147     /***
148      * Reads the characters up to the next default end-of-field marker
149      */
150     public String readString() throws IOException
151     {
152         return readString(defaultEoField);
153     }
154 
155     /***
156      * Reads the characters up to the next occurence of the given end-of-field
157      * marker, ignoring all initial spaces.
158      */
159     public String readString(char eoFieldMarker) throws IOException
160     {
161         StringBuffer returnString = new StringBuffer();
162         
163         int c = read();
164         
165         //read spaces
166         while ( c == AsciiCodes.SPACE) c = read();
167         
168         //read until end of field marker found
169         while (( c != eoFieldMarker) && !charIsEOLine(c)) {
170             returnString.append((char) c);
171             c =  read();
172         }
173         
174         isEOL = charIsEOLine(c);    //mark if reached end of line
175         
176         return returnString.toString();
177     }
178     
179     /***
180      * Reads the next number of characters corresponding to the given column
181      * width
182      */
183     public String readString(int width) throws IOException
184     {
185         StringBuffer returnString = new StringBuffer();
186         
187         int c = AsciiCodes.NUL;
188         
189         while ((width > 0) && !charIsEOLine(c)) {
190             c = read();
191             
192             if (!charIsEOLine(c)) {
193                 returnString.append( (char) c);
194             }
195             
196             width --;
197         }
198         
199         isEOL = charIsEOLine(c);    //mark if reached end of line
200         
201         return returnString.toString();
202     }
203     
204     /***
205      * Reads to the end of the line, returning all characters from the current
206      * point to there.  If the pointer is already at the end of the line (due
207      * to reading the last field, for example), nothing happens but the next
208      * read will start the next line.
209     */
210     public String readToEOL() throws IOException {
211         
212         int c = AsciiCodes.NUL;
213         StringBuffer line = new StringBuffer();
214         
215         //if we've already reached the end of line, eg due to a readString(),
216         //we don't want to do this as we'll end up reading the complete next
217         //line
218         if (!isEOL) {
219             while ((c != c_eoFile) && (c != c_eoLine)) {
220                 c = read();
221                 line.append( (char) c);
222             }
223         }
224         
225         isEOL = false;
226         
227         return line.toString();
228     }
229 }
230