1 /*
2 * STFFile.java
3 *
4 * Created on 26. November 2001, 17:40
5 *
6 * Copyright 2001 by Flo Ledermann flo@subnet.at
7 *
8 * Licensed under GNU General Public License (GPL).
9 * See http://www.gnu.org/copyleft/gpl.html
10 */
11
12 package edu.psu.geovista.app.parvis.file;
13
14 import edu.psu.geovista.app.parvis.model.*;
15 import edu.psu.geovista.app.parvis.gui.ProgressEvent;
16 import edu.psu.geovista.app.parvis.gui.ProgressListener;
17
18 import java.io.*;
19 import java.net.*;
20 import java.util.*;
21
22
23 /***
24 * A Simple file parser for reading STF (Simple Table Fomrat) files from URLs.
25 *
26 * The STF File format is defined as follows:
27 <pre>
28 # test.stf
29 # Comments have # in the first column.
30 # Type the number of fields, on a line by itself.
31 3
32 # Then type field names and types. Field names must not contain
33 # spaces.
34 #
35 PersonName String
36 Age Integer
37 HourlyWage Real
38 #
39 # Data type is case-insensitive.
40 # Default data delimiters are tabs and spaces.
41 # Here's the data, tab-delimited. Notice that the data columns are
42 # in the order they are listed above.
43 #
44 Joe 23 5.75
45 Mary 18 4.75
46 Fred 54 100.00
47 Ginger 48 100.00
48 #
49 # Nothing special is required to end the file.
50
51 </pre>
52 *
53 * Once the file is read and parsed, the data can be accessed with the methods
54 * defined in the ParallelSpaceModel interface.
55 *
56 * @author Flo Ledermann flo@subnet.at
57 * @version 0.1
58 */
59 public class STFFile extends SimpleParallelSpaceModel {
60
61 /*** The url of the file. */
62 URL url;
63
64 private int tempNumDimensions;
65
66 private int bytesRead = 0;
67 private int filesize = 0;
68
69 private Vector stringLabels = new Vector();
70 private boolean isStringLabel[];
71
72 /***
73 * Creates a new STFFile with the given url. The content is not read until
74 * readContents() is called.
75 *
76 * @param url The url of the file to read.
77 */
78 public STFFile(URL url) {
79 this.url = url;
80 }
81
82 /***
83 * Reads the contents of the file and exposes them vis the ParallelSpaceModel
84 * interface of the class. String values are stripped out of the model and
85 * set as record labels.
86 */
87 public void readContents() throws IOException{
88
89 fireProgressEvent(new ProgressEvent(this, ProgressEvent.PROGRESS_START, 0.0f, "loading file"));
90
91 URLConnection conn = url.openConnection();
92 conn.connect();
93
94 filesize = conn.getContentLength();
95 //System.out.println("filesize: " + filesize);
96
97 InputStreamReader in = new InputStreamReader(conn.getInputStream());
98
99 readFirstLine(in);
100 readHeaderLines(in);
101 readData(in);
102
103 fireProgressEvent(new ProgressEvent(this, ProgressEvent.PROGRESS_FINISH, 1.0f, "loading file"));
104
105 }
106
107 /***
108 * Reads the first data line of the file and sets up the number of dimensions.
109 */
110 protected void readFirstLine(Reader in) throws IOException{
111 String line = readLine(in);
112 bytesRead += line.length();
113
114 if (line.indexOf(' ') != -1)
115 tempNumDimensions = Integer.parseInt(line.substring(0,line.indexOf(' ')));
116 else
117 tempNumDimensions = Integer.parseInt(line);
118
119 ////System.out.println("num dimensions: " + tempNumDimensions);
120
121 isStringLabel = new boolean[tempNumDimensions];
122 for (int i=0; i<tempNumDimensions; i++){
123 isStringLabel[i] = false;
124 }
125 }
126
127 /***
128 * Reads the header lines and sets up the variable types.
129 */
130 protected void readHeaderLines(Reader in) throws IOException{
131 int i;
132 int j=0;
133 String line;
134
135 int numDimensions = tempNumDimensions;
136 Vector labels = new Vector();
137
138 for (i=0; i<tempNumDimensions; i++){
139 line = readLine(in);
140 bytesRead += line.length();
141
142 StringTokenizer str = new StringTokenizer(line);
143 String label = str.nextToken();
144 String type = str.nextToken();
145
146 if (type.equalsIgnoreCase("string")){
147 isStringLabel[i] = true;
148 stringLabels.addElement(label);
149
150 numDimensions--;
151 ////System.out.println("Recordlabel " + label);
152 }
153 else {
154 labels.addElement(label);
155 //System.out.println("Axis " + j++ + " label " + label + " type " + type + ".");
156 }
157
158 }
159
160 this.initNumDimensions(numDimensions);
161 String tempLabels[] = (String[])labels.toArray(new String[numDimensions]);
162 this.setAxisLabels(tempLabels);
163 }
164
165 /***
166 * Reads the data lines.
167 */
168 protected void readData(Reader in) throws IOException{
169 String line, value;
170 int i, j, s;
171
172 String label;
173
174 float curVal[];
175
176 while ((line = readLine(in)) != null){
177 bytesRead += line.length();
178
179 float progress = (float)bytesRead / filesize;
180 fireProgressEvent(new ProgressEvent(this, ProgressEvent.PROGRESS_UPDATE, progress, "loading file"));
181
182 StringTokenizer str = new StringTokenizer(line);
183 curVal = new float[numDimensions];
184
185 j=0;
186 s=0;
187 label = null;
188
189 for (i = 0; i<tempNumDimensions; i++){
190 value = str.nextToken();
191 // //System.out.println("value " + i + ": " + value);
192
193 if (!isStringLabel[i]) {
194 try {
195 float val = Float.parseFloat(value);
196 curVal[j++] = val;
197 }
198 catch (NumberFormatException nfe){
199 //System.out.println("Invalid Number Format: " + nfe.getMessage() + " -> dicarding & setting 0.0f");
200 curVal[j++] = 0.0f;
201 }
202 }
203 else {
204 if (label == null) {
205 label = stringLabels.elementAt(s++) + ": " + value;
206 }
207 else {
208 label += "\n" + stringLabels.elementAt(s++) + ": " + value;
209 }
210 }
211
212 }
213
214 addRecord(curVal, label);
215
216 }
217 }
218
219 /***
220 * Reads on line, skipping comments and empty lines.
221 */
222 protected String readLine(Reader in) throws IOException{
223 char buf[] = new char[128];
224 int offset = 0;
225 int ch;
226
227 boolean skip = false;
228
229 for (;;) {
230 ch = in.read();
231
232 if (ch == -1){
233 break;
234 }
235
236 if (ch == '\n' || ch == '\r') {
237 if (offset == 0 && !skip){
238 //skip empty line -> do nothing
239 skip = true;
240 // //System.out.println("skipping line: empty");
241 }
242
243 if (skip){
244 // next line reached -> stop skipping
245 skip = false;
246 }
247 else {
248 // line finished -> break and return
249 break;
250 }
251 }
252 else if(ch == '#' && offset == 0){
253 // skip this line
254 skip = true;
255 // //System.out.println("skipping line: comment");
256 }
257 else if (!skip){
258 if (offset == buf.length) {
259 char tmpbuf[] = buf;
260 buf = new char[tmpbuf.length * 2];
261 System.arraycopy(tmpbuf, 0, buf, 0, offset);
262 }
263 buf[offset++] = (char) ch;
264 }
265
266 }
267
268 if ((offset == 0) || skip){ //eof
269 return null;
270 }
271 return String.copyValueOf(buf, 0, offset);
272 }
273
274 private Vector progressListeners = new Vector();
275
276 public void addProgressListener(ProgressListener l){
277 progressListeners.add(l);
278 }
279
280 public void removeProgressListener(ProgressListener l){
281 progressListeners.remove(l);
282 }
283
284 public void fireProgressEvent(ProgressEvent e){
285 Vector list = (Vector)progressListeners.clone();
286 for (int i=0; i<list.size(); i++){
287 ProgressListener l = (ProgressListener)list.elementAt(i);
288 l.processProgressEvent(e);
289 }
290 }
291
292 /***
293 * Main method for testing purposes.
294 */
295 public static void main(String args[]){
296 try {
297 STFFile f = new STFFile(new URL("file:///d:/uni/visualisierung/datasets/table1.stf"));
298
299 f.readContents();
300 }
301 catch (MalformedURLException e){
302 //System.out.println("malformed url!");
303 }
304 catch (IOException ex){
305 //System.out.println("IOException: " + ex.getMessage());
306 }
307
308 }
309
310 }
This page was automatically generated by Maven