Class WKBHexFileReader

  1 /*
  2  * Copyright (c) 2016 Martin Davis.
  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 WKBHex format 
 28  * from a text file.
 29  * Each WKBHex geometry must be on a single line
 30  * The geometries in the file may be separated by any amount
 31  * of whitespace and newlines.
 32  * 
 33  * @author Martin Davis
 34  *
 35  */
 36 public class WKBHexFileReader 
 37 {
 38     private File file = null;
 39   private Reader reader;
 40     private WKBReader wkbReader;
 41     private int count = 0;
 42     private int limit = -1;
 43     private int offset = 0;
 44     
 45   /**
 46    * Creates a new <tt>WKBHexFileReader</tt> given the <tt>File</tt> to read from 
 47    * and a <tt>WKTReader</tt> to use to parse the geometries.
 48    * 
 49    * @param file the <tt>File</tt> to read from
 50    * @param wkbReader the geometry reader to use
 51    */
 52     public WKBHexFileReader(File file, WKBReader wkbReader)
 53     {
 54         this.file = file;
 55     this.wkbReader = wkbReader;
 56     }
 57     
 58   /**
 59    * Creates a new <tt>WKBHexFileReader</tt>, given the name of the file to read from.
 60    * 
 61    * @param filename the name of the file to read from
 62    * @param wkbReader the geometry reader to use
 63    */
 64   public WKBHexFileReader(String filename, WKBReader wkbReader)
 65   {
 66     this(new File(filename), wkbReader);
 67   }
 68   
 69   /**
 70    * Creates a new <tt>WKBHexFileReader</tt>, given a {@link Reader} to read from.
 71    * 
 72    * @param reader the reader to read from
 73    * @param wkbReader the geometry reader to use
 74    */
 75   public WKBHexFileReader(Reader reader, WKBReader wkbReader)
 76   {
 77     this.reader = reader;
 78     this.wkbReader = wkbReader;
 79   }
 80   
 81     /**
 82      * Sets the maximum number of geometries to read.
 83    * 
 84      * @param limit the maximum number of geometries to read
 85      */
 86     public void setLimit(int limit)
 87     {
 88         this.limit = limit;
 89     }
 90     
 91     /**
 92      * Sets the number of geometries to skip before storing.
 93    * 
 94      * @param offset the number of geometries to skip
 95      */
 96     public void setOffset(int offset)
 97     {
 98         this.offset = offset;
 99     }
100     
101     /**
102      * Reads a sequence of geometries.
103      * If an offset is specified, geometries read up to the offset count are skipped.
104      * If a limit is specified, no more than <tt>limit</tt> geometries are read.
105      * 
106      * @return the list of geometries read
107      * @throws IOException if an I/O exception was encountered
108      * @throws ParseException if an error occurred reading a geometry
109      */
110     public List read() 
111     throws IOException, ParseException 
112     {
113     // do this here so that constructors don't throw exceptions
114     if (file != null)
115       reader = new FileReader(file);
116     
117         count = 0;
118         try {
119             BufferedReader bufferedReader = new BufferedReader(reader);
120             try {
121                 return read(bufferedReader);
122             } finally {
123                 bufferedReader.close();
124             }
125         } finally {
126             reader.close();
127         }
128     }
129     
130     private List read(BufferedReader bufferedReader) throws IOException,
131             ParseException {
132         List geoms = new ArrayList();
133         while (! isAtEndOfFile(bufferedReader) && ! isAtLimit(geoms)) {
134           String line = bufferedReader.readLine().trim();
135           if (line.length() == 0
136             continue;
137             Geometry g = wkbReader.read(WKBReader.hexToBytes(line));
138             if (count >= offset)
139                 geoms.add(g);
140             count++;
141         }
142         return geoms;
143     }
144     
145     private boolean isAtLimit(List geoms)
146     {
147         if (limit < 0return false;
148         if (geoms.size() < limit) return false;
149         return true;
150     }
151     
152   private static final int MAX_LOOKAHEAD = 1000;
153   
154   /**
155      * Tests if reader is at EOF.
156      */
157     private boolean isAtEndOfFile(BufferedReader bufferedReader)
158             throws IOException 
159             {
160         bufferedReader.mark(MAX_LOOKAHEAD);
161  
162         StreamTokenizer tokenizer = new StreamTokenizer(bufferedReader);
163         int type = tokenizer.nextToken();
164  
165         if (type == StreamTokenizer.TT_EOF) {
166             return true;
167         }
168         bufferedReader.reset();
169         return false;
170     }
171 }
172