📄 shapefiledatastore.java
字号:
/*
* GeoTools - OpenSource mapping toolkit
* http://geotools.org
* (C) 2002-2006, Geotools Project Managment Committee (PMC)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.data.shapefile;
import static org.geotools.data.shapefile.ShpFileType.DBF;
import static org.geotools.data.shapefile.ShpFileType.PRJ;
import static org.geotools.data.shapefile.ShpFileType.SHP;
import static org.geotools.data.shapefile.ShpFileType.SHP_XML;
import static org.geotools.data.shapefile.ShpFileType.SHX;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.geotools.data.AbstractFileDataStore;
import org.geotools.data.DataSourceException;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultFIDReader;
import org.geotools.data.EmptyFeatureReader;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Query;
import org.geotools.data.ResourceInfo;
import org.geotools.data.ServiceInfo;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.dbf.DbaseFileException;
import org.geotools.data.shapefile.dbf.DbaseFileHeader;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.data.shapefile.prj.PrjFileReader;
import org.geotools.data.shapefile.shp.IndexFile;
import org.geotools.data.shapefile.shp.JTSUtilities;
import org.geotools.data.shapefile.shp.ShapeType;
import org.geotools.data.shapefile.shp.ShapefileException;
import org.geotools.data.shapefile.shp.ShapefileHeader;
import org.geotools.data.shapefile.shp.ShapefileReader;
import org.geotools.data.shapefile.shp.ShapefileWriter;
import org.geotools.data.shapefile.shp.xml.ShpXmlFileReader;
import org.geotools.factory.Hints;
import org.geotools.feature.AttributeTypeBuilder;
import org.geotools.feature.FeatureTypes;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.feature.type.BasicFeatureTypes;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.StyleAttributeExtractor;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryType;
import org.opengis.filter.Filter;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
/**
* A DataStore implementation which allows reading and writing from Shapefiles.
*
* @author Ian Schneider
*
* @todo fix file creation bug
* @source $URL:
* http://svn.geotools.org/geotools/trunk/gt/modules/plugin/shapefile/src/main/java/org/geotools/data/shapefile/ShapefileDataStore.java $
*/
public class ShapefileDataStore extends AbstractFileDataStore {
// This is the default character as specified by the DBF specification
public static final Charset DEFAULT_STRING_CHARSET = Charset
.forName("ISO-8859-1");
/**
* The query hints we do support
*/
private static final Set HINTS = Collections.unmodifiableSet(new HashSet(
Arrays.asList(new Object[] { Hints.FEATURE_DETACHED })));
protected final ShpFiles shpFiles;
protected URI namespace = null; // namespace provided by the constructor's
// map
protected SimpleFeatureType schema; // read only
protected boolean useMemoryMappedBuffer = true;
protected Charset dbfCharset;
private ServiceInfo info;
private ResourceInfo resourceInfo;
/**
* Creates a new instance of ShapefileDataStore.
*
* @param url
* The URL of the shp file to use for this DataSource.
*
* @throws NullPointerException
* DOCUMENT ME!
* @throws .
* If computation of related URLs (dbf,shx) fails.
*/
public ShapefileDataStore(URL url) throws java.net.MalformedURLException {
this(url, false, DEFAULT_STRING_CHARSET);
}
public ShapefileDataStore(URL url, boolean useMemoryMappedBuffer)
throws java.net.MalformedURLException {
this(url, useMemoryMappedBuffer, DEFAULT_STRING_CHARSET);
}
public ShapefileDataStore(URL url, boolean useMemoryMappedBuffer,
Charset dbfCharset) throws java.net.MalformedURLException {
this(url, null, false, dbfCharset);
}
/**
* this sets the datastore's namespace during construction (so the schema -
* FeatureType - will have the correct value) You can call this with
* namespace = null, but I suggest you give it an actual namespace.
*
* @param url
* @param namespace
*/
public ShapefileDataStore(URL url, URI namespace)
throws java.net.MalformedURLException {
this(url, namespace, false, DEFAULT_STRING_CHARSET);
}
/**
* this sets the datastore's namespace during construction (so the schema -
* FeatureType - will have the correct value) You can call this with
* namespace = null, but I suggest you give it an actual namespace.
*
* @param url
* @param namespace
* @param useMemoryMapped
* @param dbfCharset
*/
public ShapefileDataStore(URL url, URI namespace, boolean useMemoryMapped,
Charset dbfCharset) throws java.net.MalformedURLException {
shpFiles = new ShpFiles(url);
this.namespace = namespace;
if (!isLocal() || !shpFiles.exists(SHP)) {
this.useMemoryMappedBuffer = false;
} else {
this.useMemoryMappedBuffer = useMemoryMapped;
}
this.useMemoryMappedBuffer = useMemoryMapped;
this.dbfCharset = dbfCharset;
}
/**
* this sets the datastore's namespace during construction (so the schema -
* FeatureType - will have the correct value) You can call this with
* namespace = null, but I suggest you give it an actual namespace.
*
* @param url
* @param namespace
* @param useMemoryMapped
*/
public ShapefileDataStore(URL url, URI namespace, boolean useMemoryMapped)
throws java.net.MalformedURLException {
this(url, namespace, useMemoryMapped, DEFAULT_STRING_CHARSET);
}
/**
* Access a ServiceInfo object for this shapefile.
*
* @return ShapefileServiceInfo describing service.
*/
public synchronized ServiceInfo getInfo(){
if( info == null ){
if( isLocal() ){
info = new ShapefileFileServiceInfo( this );
}
else {
info = new ShapefileURLServiceInfo( this );
}
}
return info;
}
/**
* Used by FeatureSource<SimpleFeatureType, SimpleFeature> / FeatureStore / FeatureLocking to
* access a single ResourceInfo.
*
* @param typeName
* @return ResourceInfo
*/
synchronized ResourceInfo getInfo( String typeName ) {
if( resourceInfo == null ){
if( isLocal() ){
// we may be able to make this instance writable
// allowing users to store values into shapefile metadata?
resourceInfo = new ShapefileFileResourceInfo( this );
}
else {
resourceInfo = new ShapefileURLResourceInfo( this );
}
}
return resourceInfo;
}
/**
* Set this if you need BDF strings to be decoded in a {@link Charset} other
* than ISO-8859-1
*
* @param stringCharset
* @since 2.3.3
*/
public void setStringCharset(Charset stringCharset) {
this.dbfCharset = stringCharset;
}
/**
* Returns the {@link Charset} used to decode strings in the DBF file
*
* @return
*/
public Charset getStringCharset() {
return dbfCharset;
}
/**
* Latch onto xmlURL if it is there, we may be able to get out of
* calculating the bounding box!
*
* <p>
* This method is called by the createTypeEntry anonymous inner class
* DefaultTypeEntry.
* </p>
*
* @param typeName
* DOCUMENT ME!
*
* @return Map with xmlURL parsed, or an EMPTY_MAP.
*/
protected Map createMetadata(String typeName) {
String urlString = shpFiles.get(SHP_XML);
if (urlString == null) {
return Collections.EMPTY_MAP;
}
try {
// System.out.println("found metadata = " + xmlURL);
ShpXmlFileReader reader = new ShpXmlFileReader(shpFiles);
Map map = new HashMap();
map.put("shp.xml", reader.parse());
// System.out.println("parsed ..." + xmlURL);
return map;
} catch (Throwable t) {
LOGGER.warning("Could not parse " + urlString + ":"
+ t.getLocalizedMessage());
return Collections.EMPTY_MAP;
}
}
/**
* Determine if the location of this shapefile is local or remote.
*
* @return true if local, false if remote
*/
public boolean isLocal() {
return shpFiles.isLocal();
}
/**
* Create a FeatureReader<SimpleFeatureType, SimpleFeature> for the provided type name.
*
* @param typeName
* The name of the FeatureType to create a reader for.
*
* @return A new FeatureReader.
*
* @throws IOException
* If an error occurs during creation
*/
protected FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader(String typeName)
throws IOException {
typeCheck(typeName);
return getFeatureReader();
}
protected FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader() throws IOException {
try {
return createFeatureReader(getSchema().getTypeName(),
getAttributesReader(true), schema);
} catch (SchemaException se) {
throw new DataSourceException("Error creating schema", se);
}
}
/**
* Just like the basic version, but adds a small optimization: if no
* attributes are going to be read, don't uselessly open and read the dbf
* file. Makes sure to consider also attributes in the query.
*
* @see org.geotools.data.AbstractDataStore#getFeatureReader(java.lang.String,
* org.geotools.data.Query)
*/
protected FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader(String typeName, Query query)
throws IOException {
String[] propertyNames = query.getPropertyNames();
String defaultGeomName = schema.getDefaultGeometry().getLocalName();
// gather attributes needed by the query tool, they will be used by the
// query filter
StyleAttributeExtractor extractor = new StyleAttributeExtractor();
Filter filter = query.getFilter();
filter.accept(extractor, null);
String[] filterAttnames = extractor.getAttributeNames();
// check if the geometry is the one and only attribute needed
// to return attribute _and_ to run the query filter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -