GeoTools 读取Shapefile文件

关注我,带你一起学GIS ^

此文上接

  • GIS 开发库 GeoTools 介绍
  • GeoTools 开发环境搭建

本文将讲解如何使用GeoTools读取Shpfile文件,若还没有阅读过前两篇文章,建议先观看一下。

开发环境

产品:GeoTools

版本:34-SNAPSHOT

时间:2025年

IDE:IDEA2020.3

1. 安装依赖

确保pom.xml文件中已经配置gt-shapefile依赖模块并且已经使用Maven下载。

<dependency>
  <groupId>org.geotools</groupId>
  <artifactId>gt-shapefile</artifactId>
  <version>${geotools.version}</version>
</dependency>

2. 读取Shp

新建一个类用来读取Shpfile文件,在main或者自定义方法中处理逻辑。

String provinceLocation = "E:\data\基础数据\行政区\省级行政区\省级行政区\省.shp";
File file = new File(provinceLocation);

// 文件存储器
FileDataStore dataStore = FileDataStoreFinder.getDataStore(file.toURI().toURL());

// 获取要素源
SimpleFeatureSource featureSource = dataStore.getFeatureSource();

// 获取要素集合
SimpleFeatureCollection featureCollection = featureSource.getFeatures();

try{
    // 遍历要素
    try(SimpleFeatureIterator iterator = featureCollection.features()){
        while (iterator.hasNext()){
            // 获取要素
            SimpleFeature feature = iterator.next();

            // 获取几何对象
            Geometry geometry = (Geometry) feature.getDefaultGeometry();

            // 获取要素属性
            Property property = feature.getProperties()
        }
    }
    // 关闭存储
    dataStore.dispose();
}catch (Exception e){
    e.printStackTrace();
}finally {
    if (dataStore != null) {
        // 确保关闭DataStore
        dataStore.dispose(); 
    }
}

其中getDataStore()方法接受两种形式的参数,既可以是文件也可以是URL

FileDataStoreFinder.getDataStore(file)FileDataStoreFinder.getDataStore(file.toURI().toURL())

在数据读取完成后要使用dataStore.dispose()关闭存储器。

3. 读取属性表结构

通过featureSource.getSchema()可以获取到表结构信息,包括属性字段和几何字段。

// 读取属性表结构
SimpleFeatureType schema = featureSource.getSchema();
System.out.println("几何字段: " + schema.getGeometryDescriptor().getLocalName());

// 属性字段
for(AttributeDescriptor descriptor:schema.getAttributeDescriptors()){
   System.out.println(descriptor.getLocalName()+":"+descriptor.getType().getBinding().getSimpleName());
}

如本例中输出属性结构如下,读取出来的几何字段名称为the_geom,类型为MultiPolygon,其他为属性字段及类型。

4. 读取坐标系统

通过getCoordinateReferenceSystem可以获取坐标信息。

// 坐标系统
CoordinateReferenceSystem crs = schema.getCoordinateReferenceSystem();
System.out.println("坐标系统:"+crs);

如本例中的Shp文件坐标系为大地坐标系WGS84

// String worldLocation = "E:\data\基础数据\世界\ne_10m_admin_0_countries\ne_10m_admin_0_countries.shp";
String provinceLocation = "E:\data\基础数据\行政区\省级行政区\省级行政区\省.shp";
File file = new File(provinceLocation);

Map<String,Object> params = new HashMap<>();
params.put("url",file.toURI().toURL());
params.put("charset","UTF-8");

// 文件存储器
//FileDataStore dataStore = FileDataStoreFinder.getDataStore(file.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(params);

String typeName = dataStore.getTypeNames()[0];
// 获取要素源
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);

// 获取要素集合
SimpleFeatureCollection featureCollection = featureSource.getFeatures();

// 读取属性表结构
SimpleFeatureType schema = featureSource.getSchema();
// System.out.println("几何字段: " + schema.getGeometryDescriptor().getLocalName());

for(AttributeDescriptor descriptor:schema.getAttributeDescriptors()){
   // System.out.println(descriptor.getLocalName()+":"+descriptor.getType().getBinding().getSimpleName());
}

// 坐标系统
CoordinateReferenceSystem crs = schema.getCoordinateReferenceSystem();
System.out.println("坐标系统:"+crs.getName());
try{
    // 遍历要素
    try(SimpleFeatureIterator iterator = featureCollection.features()){
        while (iterator.hasNext()){
            SimpleFeature feature = iterator.next();
            // 输出要素
            // System.out.println("要素:"+feature);

            // 获取几何对象
            Geometry geometry = (Geometry) feature.getDefaultGeometry();
            // System.out.println("几何对象:"+geometry);

            // 输出属性
            // System.out.println("属性:"+feature.getProperties());
            // 获取要素属性
            for (Property property : feature.getProperties()){
                System.out.println(property.getName()+":"+property.getValue());
            }
        }
    }
    // 关闭存储
    dataStore.dispose();
}catch (Exception e){
    e.printStackTrace();
}finally {
    if (dataStore != null) {
        dataStore.dispose(); // 确保关闭DataStore
    }
}

5. 遇到问题及处理方法

  1. 读取Shp文件报错:某某文件已锁定。

严重: The following locker still has a lock: read on file:/E:/data/基础数据/行政区/省级行政区/省级行政区/省.dbf by org.geotools.data.shapefile.dbf.DbaseFileReaderjava.lang.IllegalArgumentException: Expected requestor org.geotools.data.shapefile.dbf.DbaseFileReader@30c31dd7 to have locked the url but it does not hold the lock for the URL

产生原因:在Shp数据读取过程中未正确关闭文件存储器。解决方案:需在正确的位置,也就是数据读取完成之后关闭存储器dataStore.dispose()

try{
    // 遍历要素
    try(SimpleFeatureIterator iterator = featureCollection.features()){
       // 此处进行业务处理
    }
    // 关闭存储
    dataStore.dispose();
}catch (Exception e){
    e.printStackTrace();
}finally {
    if (dataStore != null) {
        // 确保关闭DataStore
        dataStore.dispose(); 
    }
}
  1. 中文乱码问题

如在本例中读取省级行政区时,行政区名称Name字段出现了中文乱码问题。经过修改后中文正常显示如下。

产生原因:未正确识别或者设置字符集。解决方案:在读取Shp文件前,将字符集设置为"GBK"

// 定义文件参数
Map<String,Object> params = new HashMap<>();
params.put("url",file.toURI().toURL());
params.put("charset","GBK");

// 文件存储器
//FileDataStore dataStore = FileDataStoreFinder.getDataStore(file.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(params);

String typeName = dataStore.getTypeNames()[0];
// 获取要素源
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
  1. 如何查看Shp文件字符集

正常情况下,在Shp文件中会有一个.cpg后缀文件,在该文件中存储着字符集信息。如果没有也可以新建一个文本文件,将后缀改为.cpg,然后填入正确的字符集。在读取Shp文件前,将存储器参数字符集修改为目标字符集即可。

OpenLayers示例数据下载,请在公众号后台回复:ol数据

全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试

GIS之路公众号已经接入了智能助手,欢迎大家前来提问。

欢迎访问我的博客网站-长谈GIShttp://shanhaitalk.com

都看到这了,不要忘记点赞、收藏+关注 

本号不定时更新有关 GIS开发  相关内容,欢迎关注 

 

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部