Class WKTFileReader

  1 /*
  2  * Copyright (c) 2016 Vivid Solutions.
  3  *
  4  * All rights reserved. This program and the accompanying materials
  5  * are made available under the terms of the Eclipse Public License 2.0
  6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  8  * and the Eclipse Distribution License is available at
  9  *
 10  * http://www.eclipse.org/org/documents/edl-v10.php.
 11  */
 12  
 13 package org.locationtech.jts.io;
 14  
 15 import java.io.BufferedReader;
 16 import java.io.File;
 17 import java.io.FileReader;
 18 import java.io.IOException;
 19 import java.io.Reader;
 20 import java.io.StreamTokenizer;
 21 import java.util.ArrayList;
 22 import java.util.List;
 23  
 24 import org.locationtech.jts.geom.Geometry;
 25  
 26 /**
 27  * Reads a sequence of {@link Geometry}s in WKT format 
 28  * from a text file.
 29  * The geometries in the file may be separated by any amount
 30  * of whitespace and newlines.
 31  * 
 32  * @author Martin Davis
 33  *
 34  */
 35 public class WKTFileReader 
 36 {
 37     private File file = null;
 38   private Reader reader;
 39 //  private Reader fileReader = new FileReader(file);
 40     private WKTReader wktReader;
 41     private int count = 0;
 42     private int limit = -1;
 43     private int offset = 0;
 44   private boolean isStrictParsing = true;
 45     
 46   /**
 47    * Creates a new <tt>WKTFileReader</tt> given the <tt>File</tt> to read from 
 48    * and a <tt>WKTReader</tt> to use to parse the geometries.
 49    * 
 50    * @param file the <tt>File</tt> to read from
 51    * @param wktReader the geometry reader to use
 52    */
 53     public WKTFileReader(File file, WKTReader wktReader)
 54     {
 55         this.file = file;
 56     this.wktReader = wktReader;
 57     }
 58     
 59   /**
 60    * Creates a new <tt>WKTFileReader</tt>, given the name of the file to read from.
 61    * 
 62    * @param filename the name of the file to read from
 63    * @param wktReader the geometry reader to use
 64    */
 65   public WKTFileReader(String filename, WKTReader wktReader)
 66   {
 67     this(new File(filename), wktReader);
 68   }
 69   
 70   /**
 71    * Creates a new <tt>WKTFileReader</tt>, given a {@link Reader} to read from.
 72    * 
 73    * @param reader the reader to read from
 74    * @param wktReader the geometry reader to use
 75    */
 76   public WKTFileReader(Reader reader, WKTReader wktReader)
 77   {
 78     this.reader = reader;
 79     this.wktReader = wktReader;
 80   }
 81   
 82   /**
 83    * Sets the maximum number of geometries to read.
 84    * 
 85    * @param limit the maximum number of geometries to read
 86    */
 87   public void setLimit(int limit)
 88   {
 89     this.limit = limit;
 90   }
 91   
 92   /**
 93    * Allows ignoring WKT parse errors 
 94    * after at least one geometry has been read,
 95    * to return a partial result.
 96    * 
 97    * @param isLenient whether to ignore parse errors
 98    */
 99   public void setStrictParsing(boolean isStrict)
100   {
101     this.isStrictParsing = isStrict;
102   }
103   
104     /**
105      * Sets the number of geometries to skip before storing.
106    * 
107      * @param offset the number of geometries to skip
108      */
109     public void setOffset(int offset)
110     {
111         this.offset = offset;
112     }
113     
114     /**
115      * Reads a sequence of geometries.
116      * If an offset is specified, geometries read up to the offset count are skipped.
117      * If a limit is specified, no more than <tt>limit</tt> geometries are read.
118      * 
119      * @return the list of geometries read
120      * @throws IOException if an I/O exception was encountered
121      * @throws ParseException if an error occurred reading a geometry
122      */
123     public List read() 
124     throws IOException, ParseException 
125     {
126     // do this here so that constructors don't throw exceptions
127     if (file != null)
128       reader = new FileReader(file);
129     
130         count = 0;
131         try {
132             BufferedReader bufferedReader = new BufferedReader(reader);
133             try {
134                 return read(bufferedReader);
135             } finally {
136                 bufferedReader.close();
137             }
138         } finally {
139             reader.close();
140         }
141     }
142     
143   private List read(BufferedReader bufferedReader) 
144       throws IOException, ParseException {
145     List geoms = new ArrayList();
146     try {
147       read(bufferedReader, geoms);
148     }
149     catch (ParseException ex) {
150       // throw if strict or error is on first geometry
151       if (isStrictParsing || geoms.size() == 0)
152         throw ex;
153     }
154     return geoms;
155   }
156  
157   private void read(BufferedReader bufferedReader, List geoms) 
158       throws IOException, ParseException {
159     while (!isAtEndOfFile(bufferedReader) && !isAtLimit(geoms)) {
160       Geometry g = wktReader.read(bufferedReader);
161       if ( count >= offset )
162         geoms.add(g);
163       count++;
164     }
165   }
166  
167     private boolean isAtLimit(List geoms)
168     {
169         if (limit < 0return false;
170         if (geoms.size() < limit) return false;
171         return true;
172     }
173     
174   private static final int MAX_LOOKAHEAD = 1000;
175   
176   /**
177      * Tests if reader is at EOF.
178      */
179     private boolean isAtEndOfFile(BufferedReader bufferedReader)
180             throws IOException 
181             {
182         bufferedReader.mark(MAX_LOOKAHEAD);
183  
184         StreamTokenizer tokenizer = new StreamTokenizer(bufferedReader);
185         int type = tokenizer.nextToken();
186  
187         if (type == StreamTokenizer.TT_EOF) {
188             return true;
189         }
190         bufferedReader.reset();
191         return false;
192     }
193 }
194