⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shapefiledatastore.java

📁 shape file read and write
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 *    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 + -