在Java中基于GeoTools的Shapefile读取乱码的问题解决办法

news2024/9/22 10:19:06

目录

前言

1、Shapefile属性字段编码的情况:

一、Shp文件常见的字符集编码

1、System编码

2、ISO-8859-1编码

3、UTF-8编码 

二、GeoTools解析实战

1、未进行字符处理

2、乱码问题的解决

3、转码支持

4、属性字段编码结果

三、总结


前言

        文件编码(File Encoding)是指文件在计算机中存储时所使用的字符编码方式。字符编码是将字符(如字母、数字、标点符号等)转换成计算机可以直接存储和处理的数字或二进制代码的过程。不同的编码方式决定了文件中字符如何被表示和存储,以及这些字符如何被不同的软件或系统正确地读取和显示。在进行空间数据处理的时候,通常会涉及大量的空间数据,为了更加详细且准确的描述这些空间数据,我们通过会配置一些属性数据。

        Shapefile属性字段的编码通常指的是存储在shapefile的dbf(数据库文件)中的属性数据的字符编码方式。Shapefile是一种用于存储地理空间数据的文件格式,它由多个文件组成,其中dbf文件用于存储每个几何形状的属性数据。

1、Shapefile属性字段编码的情况:

默认编码:
        在不同的软件或库中,shapefile的默认编码可能有所不同。例如,ArcGIS Desktop在较新版本(如10.2.1及以后)中,shapefile (.DBF) 的编码页的默认设置为UTF-8(UNICODE)。而在一些其他软件或库中,如Java GDAL库,默认可能使用ISO-8859-1编码,这会导致中文等非西欧字符出现乱码问题。
编码设置:
        在使用某些软件或库处理shapefile时,可以通过设置来改变属性字段的编码方式。例如,在Java GDAL库中,可以通过调GDAL.SetConfigOption("SHAPE_ENCODING","UTF-8")来设置GDAL库的默认编码为UTF-8,从而避免中文属性乱码的问题。在ArcGIS中,虽然默认编码可能是UTF-8,但也可以通过修改注册表中的dbfDefault值来指定不同的编码方式。不过,这种方法主要影响ArcGIS Desktop生成的shapefile和dBASE文件的编码类型,且仅对ArcGIS Desktop生效。
编码转换:
        如果已经存在编码不匹配的shapefile文件,可能需要通过编码转换工具来修改其属性字段的编码方式。例如,可以使用FME Workbench等GIS数据转换工具来转换shapefile的编码。也可以使用编程方式,如利用geotools等库来读取原始编码的shapefile文件,并以新的编码方式重新写入数据,从而实现编码的转换。
注意事项
        在处理shapefile属性字段编码时,需要确保整个处理流程中的编码方式一致,以避免出现乱码或数据丢失等问题。如果shapefile文件是从不同来源获取的,可能需要先确认其编码方式,以便在后续处理中正确读取和写入数据。在进行编码转换时,应谨慎操作,以免损坏原始数据。建议在转换前备份原始文件,并在转换后进行验证以确保数据的完整性和准确性。

        本文主要讲述使用Java编程语言进行地理信息数据解析的时候,遇到Shapefile的属性信息乱码的几种情况,以及根据不同的编码设置来进行属性信息的解析。博文首先介绍采用不同的字符集编码的shapefile文件,然后在Qgis中打开属性表,查看相关的字符展示情况,接着说明在Java当中调用Geotools时,为经过字符编码处理和经过字符编码处理后的对比,让大家熟悉在Geotools的开发过程中,掌握字符编码的设置。

一、Shp文件常见的字符集编码

        为了讲解使用不同的编码来展示空间数据,我们首先来介绍基础的数据,即三份不同的空间数据格式,其格式都是shapefile的。但是在不同的空间记录中,其字段的值是采用不同的编码的。在这里,采用QGIS这款软件来进行属性数据的展示,方便大家了解日常中的数据展示。

1、System编码

        第一种要介绍的就是System的编码方式,这里采用的是用我国的Lake图层信息,首先我们在Qgis中打开这份数据来看一下,文件的本地路径为:

F:\vector_data\地理数据20240912\地理数据20240912\水系河流\1 全国1-5级标准河流-wgs84\主要湖泊面文件\Lake.shp

        将数据在Qgis软件中打开可以看到其主要的源信息描述如下:

        可以在编码一栏中看到,这份文件的编码是System的。 为了看到其里面的属性信息,可以右键点击shp数据,点击打开属性表就可以看到这份数据的完整的数据信息,打开后相关信息如下所示:

        在上图的红线框中很明显可以看到,有一列叫NAME的,它的值是有乱码的,并没有是我们常见的编码。 因此这算是乱码的第一种情况。

2、ISO-8859-1编码

        第二种也是常见的ISO-8859-1编码,这里准备的数据是一份湖南省的乡镇边界数据,其在文件磁盘中目录如下,:

C:\BaiduDownload\湖南省\湖南省_乡镇边界.shp

        同样的,我们使用QGis软件打开上面的乡镇边界.shp文件,打开后可以看到很明确的字符编码信息:

        同样的我们使用QGIS来进行属性数据的打开查看, 详细如下图所示:

3、UTF-8编码 

        这应该算是比较标准的编码方式,如果进行数据制作的时候,都是统一采用UTF-8的模式,那么这种方式无疑是最好的,估计也不存在字符编码的问题了。

        这个时候,在QGIS中打开属性表,其属性字段的内容是正常可以直接预览的,详情如下图所示。

        当然,字符编码的处理方式根据项目的不同,也会有不同的设置,种类繁多,不甚枚举,这里仅以这几项为例作为例子来讲解,如果以后在开发过程中,遇到这种情况,可以根据实际来进行编码的扩充和修复。 

二、GeoTools解析实战

        在上面的一节中,我们简单的对三种不同的编码方式的shapefile文件进行了简单的介绍,本节则重点介绍如何使用Java开发语言,使用GeoTools的开发组件进行编码的处理和转换,将属性数据可以成功读取到我们的应用程序中。在这里需要统一说明的是,在进行数据的处理和转换的时候,为了进行数据的演示,我们仅将数据的前10行数据记载处理,这样如果有乱码的问题,我们就可以直接进行干预,通过修改其它的字符集函数的方式来保证文字的识别与处理。

1、未进行字符处理

        首先我们来加载UTF-8的矢量数据,测试一下使用UTF-8的情况下,如何使用GeoTools的方法来进行属性表格的解析。下面来看如何使用GeoTools来进行空间属性数据的解析与展示,关键代码如下所示:

/**
* * 不做任何处理展示shp文件数据详情
* 
* @param shpFile shp文件地址
* @throws Exception
*/
protected static void showShpDetails(String shpFile) throws Exception {
	File file = new File(shpFile);
	if (!file.exists()) {
		System.out.println("文件不存在");
		return;
	}
	ShapefileDataStore store = new ShapefileDataStore(file.toURI().toURL());
	String typeName = store.getTypeNames()[0];
	// 创建一个Query对象
	Query query = new Query(typeName);
	// 设置查询返回的最大特征数为10
	query.setMaxFeatures(10);
	SimpleFeatureSource featureSource = store.getFeatureSource();
	// 执行查询
	SimpleFeatureCollection simpleFeatureCollection = featureSource.getFeatures(query);
	SimpleFeatureIterator itertor = simpleFeatureCollection.features();
	// 遍历featurecollection
	while (itertor.hasNext()) {
		SimpleFeature feature = itertor.next();
		Collection<Property> p = feature.getProperties();
		Iterator<Property> it = p.iterator();
		// 遍历feature的properties
		while (it.hasNext()) {
			Property pro = it.next();
			if (null != pro && null != pro.getValue()) {
				String field = pro.getName().toString();
				String value = pro.getValue().toString();
				System.out.println(field + "===" + value);
			}
		}
		System.out.println("-----------------------------------------------------");
	}
}

        在上面的代码中,需要注意的地方就是,我们想要在查询的时候只查10条,那么就需要使用到GeoTools的查询Query对象,通过结合Query对象来实现只查10条。10条的设置是个经验值,可以根据服务器的速度和性能来进行平衡,可以一次处理更多的数据。运行测试用例来看其读取的结果如下:

        可以看到,在IDE的控制台中,读取出来的空间属性信息都是乱码。 

2、乱码问题的解决

        要想解决乱码的问题,首先要找到根源。我们需要对属性信息字段进行字符集编码的控制。因此我们在互联网上查询一下,时候有相应的方案。在这里哪怕不管具体的方案,也要了解为什么会出现这个问题。我们来看下ShapefileDataStore这个对象,这个对象是有一个关于字符集的编码的,如下所示:

         如果看过源码的话,各位小伙伴会发现,在GeoTools中有默认的编码集,即:Charset charset = DEFAULT_STRING_CHARSET;

public static final Charset DEFAULT_STRING_CHARSET =
            (Charset) ShapefileDataStoreFactory.DBFCHARSET.getDefaultValue();

        其实现的实际逻辑代码如下:

/**
* Optional - character used to decode strings from the DBF file. If none is provided, the
* factory will instruct {@link ShapefileDataStore} to try to guess a charset from CPG file,
* before using a default value.
*
* @see ShapefileDataStore#setTryCPGFile(boolean)
*/
public static final Param DBFCHARSET =
       new Param(
           "charset",
           Charset.class,
           "character used to decode strings from the DBF file",
           false,
           StandardCharsets.ISO_8859_1,
           new KVP(Param.LEVEL, "advanced")) {
         /*
         * This is an example of a non simple Param type where a custom parse method is required.
        *
         * @see org.geotools.data.DataStoreFactorySpi.Param#parse(java.lang.String)
         */
         @Override
         public Object parse(String text) throws IOException {
              return Charset.forName(text);
         }

         @Override
         public String text(Object value) {
              return ((Charset) value).name();
         }
      };

        通过上面的代码可以看到,这里使用的默认编码是:StandardCharsets.ISO_8859_1,也就是ISO-8859-1的方式。

3、转码支持

        了解了乱码的产生原理之后,我们来进行相应的代码转换,关于编码的转换有两种方式,第一种统一在Store一层就进行转码。这样比较单一,也比较简单。第二种就是在每一个value中进行编程式转码,这样不仅麻烦,而且效率低。为了支持全局处理编码等,我们将函数进行已统一的封装,增加了自定义编码的支持:

/**
* *展示shp文件数据详情
* 
* @param shpFile      shp文件地址
* @param unifySetting 是否统一设置字符
* @param chartSet     需要设置的字符编码
* @throws Exception
*/
protected static void showShpDetails(String shpFile, boolean unifySetting, String chartSet) throws Exception {
	File file = new File(shpFile);
	if (!file.exists()) {
		System.out.println("文件不存在");
		return;
	}
	ShapefileDataStore store = new ShapefileDataStore(file.toURI().toURL());
	String typeName = store.getTypeNames()[0];
	// 创建一个Query对象
	Query query = new Query(typeName);
	// 设置查询返回的最大特征数为10
	query.setMaxFeatures(10);
	if (unifySetting) {
			store.setCharset(Charset.forName(chartSet));// 设置中文字符编码
	}
	SimpleFeatureSource featureSource = store.getFeatureSource();
	System.out.println(featureSource);
	// 执行查询
	SimpleFeatureCollection simpleFeatureCollection = featureSource.getFeatures(query);
	SimpleFeatureIterator itertor = simpleFeatureCollection.features();
	// 遍历featurecollection
	while (itertor.hasNext()) {
		SimpleFeature feature = itertor.next();
		Collection<Property> p = feature.getProperties();
		Iterator<Property> it = p.iterator();
		// 遍历feature的properties
		while (it.hasNext()) {
			Property pro = it.next();
			if (null != pro && null != pro.getValue()) {
				String field = pro.getName().toString();
				String value = pro.getValue().toString();
				if (!unifySetting) {
					// byte[]bytes= value.getBytes("iso8859-1");
					byte[] bytes = value.getBytes();
					value = new String(bytes, chartSet);
				}
				System.out.println(field + "===" + value);
			}
		}
	System.out.println("-------------------------------------------------------------");
	}
}

4、属性字段编码结果

        下面对集中情况的属性数据进行解析,将输出的成果在编辑器的控制台进行综合展示。

        可以在控制台中看到以下的数据都是正常的,

org.geotools.data.shapefile.ShapefileFeatureStore@1b6e1eff
the_geom===POINT (113.24947489555838 28.625229546432124)
名称===南门桥(公交站)
大类===交通设施服务
中类===公交车站
小类===公交车站相关
地址===星通2路
省===湖南省
市===长沙市
区===长沙县
WGS84_经===113.249474896
WGS84_纬===28.6252295464

        同理,其它的数据如湖南省乡镇边界数据,我们使用编码后来查看具体的输出。

        同样的,在控制台中可以看到以下的输出,

gml_id===layer_township_pg.15847
Name===星子镇
layer===乡镇
code===441882101000
grade===4
----------------------------------------------------------------------
gml_id===layer_township_pg.15849
Name===三水瑶族乡
layer===乡镇
code===441882201000
grade===4

        同样的,编码方式是ISO-8859-1的数据经过编码后正常显示。 到此,使用Java语言进行GeoTools解析Shp文件的属性信息时乱码的问题得到解决。

三、总结

        以上就是本文的主要内容,本文主要讲述使用Java编程语言进行地理信息数据解析的时候,遇到Shapefile的属性信息乱码的几种情况,以及根据不同的编码设置来进行属性信息的解析。博文首先介绍采用不同的字符集编码的shapefile文件,然后在Qgis中打开属性表,查看相关的字符展示情况,接着说明在Java当中调用Geotools时,为经过字符编码处理和经过字符编码处理后的对比,让大家熟悉在Geotools的开发过程中,掌握字符编码的设置。行文仓促,定有许多不足之处,如有不当之处,还恳请各位专家和博主在评论区留言支持,不胜感激。

        博文在写作过程中,参考以下,在此表示表示:

        1、shapefile与字符集编码设置。

        2、java gdal 创建shapefile属性中文乱码。

        3、shapefile与字符集编码设置。

        4、GeoTools读取shp文件中文乱码解决方案汇总。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2154832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ:交换机详解(Fanout交换机、Direct交换机、Topic交换机)

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

【笔记】第二节 轧制、热处理和焊接工艺

2.2 钢轨的轧制工艺 坯料进厂按标准验收, 然后装加热炉加热, 加热好的钢坯经高压水除鳞后进行轧制。轧出的钢轨经锯切、打印到中央冷床冷却, 然后装缓冷坑进行缓冷。缓冷后的钢轨进行矫直、轨端加工和端头淬火。钢轨入库前逐根进行探伤和外观检查。 钢轨的轧制 #mermaid-svg-…

【Delphi】使用 TPrototypeBindSource 和 LiveBindings 设计器示例

本教程展示了如何使用 LiveBindings Designer 和 TPrototypeBindSource 可视化地创建控件之间的 LiveBindings&#xff0c;以便快速开发只需很少或无需源代码的应用程序。 注意&#xff1a; TPrototypeBindSource 可用于为项目中的 LiveBindings 生成样本数据。在应用程序原型化…

公私域互通下的新商机探索:链动2+1模式、AI智能名片与S2B2C商城小程序的融合应用

摘要&#xff1a;在数字化时代&#xff0c;公私域流量的有效融合已成为企业获取持续增长动力的关键。本文旨在探讨如何通过链动21模式、AI智能名片以及S2B2C商城小程序源码的综合运用&#xff0c;实现公私域流量的高效互通&#xff0c;进而为门店创造巨大商机。通过分析这些工具…

前后端跨域问题及其在ThinkPHP中的解决方案

在现代Web开发中&#xff0c;前后端分离的架构越来越普遍&#xff0c;但这也带来了跨域问题。跨域指的是在一个域下的网页试图请求另一个域的资源&#xff0c;浏览器出于安全考虑会限制这种行为。本文将探讨如何在ThinkPHP中解决跨域问题。 #### 1. 什么是跨域&#xff1f; 跨…

C++初阶学习——模版进阶

1. 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当成…

不同编程语言的互相调用

C语言与Python 步骤&#xff1a; 编写C代码 (hello_c.c): #include <stdio.h>void printHello(const char *name) {printf("Hello, %s!\n", name); }编译C代码为共享库: gcc -shared -o hello_c.so hello_c.c编写Python代码 (hello_c_py.py): import ctypes# …

【数据库】常用数据库简介

目录 &#x1f354; 常用的关系型数据库 &#x1f354; Mysql简介 &#x1f354; SQL 简介 SQL语句的分类 SQL 写法 SQL 常用的数据类型 &#x1f354; DDL语句 对数据库的操作 对数据表的操作 &#x1f354; DML语句 插入数据 insert into 修改数据 update 删除数…

<<编码>> 第 16 章 存储器组织(3)--3-8 译码器 示例电路

3-8 译码器 info::操作说明 “写入” 开关先断开(Q 为低电平, 表示不写入) S2-S1-S0 设置一个二进制数, 选中 Q0~Q7 其中一个作为 Q 的输出 “数据输入” 端置入要保存的数(0或1) 闭合 “写入” 开关, 对应的一位锁存器中的 W 为高电平, 表示可以写入, “数据输入” 的值最终…

Java安全(加密+HTTPS+WEB安全)

Java加密 单向加密 接收一段明文&#xff0c;然后以一种不可逆的方式将它转换成一段密文 ①、MD5&#xff0c;将无论多长的数据最后编码128位数据&#xff0c;常用文件校验、密码加密、散列数据 byte[] data ...;//明文数据 MessageDigest md5 MessageDigest.getInstance…

大数据新视界 --大数据大厂之Kubernetes与大数据:容器化部署的最佳实践

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【软件资料集】系统培训方案(Word项目参考2024)

1. 培训概述 2. 培训目的 3. 培训对象及要求 3.1. 培训对象 3.2. 培训人员基本要求 4. 培训方式 5. 培训内容 6. 培训讲师 7. 培训教材 8. 培训质量保证 8.1. 用户培训确认报告 8.2. 培训疑问解答 获取方式&#xff1a;本文末个人名片直接获取。 软件资料清单列表部分文档清单&…

opencv实战项目二十四:棋盘格相机内参标定

文章目录 前言一、简介&#xff1a;二、使用步骤2.1制作标定板2.2 拍摄不同角度的标定板2.3计算棋盘格角点并优化2.4计算相机参数 三、整体代码实现&#xff1a; 前言 在数字图像处理和计算机视觉领域&#xff0c;相机标定是一个至关重要的步骤。它为相机提供了一个准确的数学…

Tomcat 乱码问题彻底解决

1. 终端乱码问题 找到 tomcat 安装目录下的 conf ---> logging.properties .修改ConsoleHandler.endcoding GBK &#xff08;如果在idea中设置了UTF-8字符集&#xff0c;这里就不需要修改&#xff09; 2. CMD命令窗口设置编码 参考&#xff1a;WIN10的cmd查看编码方式&am…

Nature|PathChat:病理学多模态生成性AI助手的创新与应用|顶刊精析·24-09-21

小罗碎碎念 今日顶刊&#xff1a;Nature 这篇文章今年6月就发表了&#xff0c;当时我分析的时候&#xff0c;还是预印本&#xff0c;没有排版。今天第一篇推文介绍的是Faisal Mahmood &#xff0c;所以又把这篇文章拉出来详细分析一下。 作者角色作者姓名单位名称单位英文名称第…

PMP--二模--解题--61-70

文章目录 4.整合管理61、 [单选] 为解决具有挑战性的客户请求&#xff0c;启动了一个项目。该项目必须在短时间内交付。项目经理应该怎么做来尽可能提高项目的成功率&#xff1f; 14.敏捷--MVP--最小可行产品--使用最小可行产品获得客户尽早地反馈。完整性和交付是主观的。团队…

构建高可用和高防御力的云服务架构第二部分:SLB负载均衡(2/5)

在现代云服务中&#xff0c;负载均衡&#xff08;Load Balancing&#xff09;是一种关键技术&#xff0c;用于优化资源利用、最小化响应时间、提高系统的可伸缩性和可靠性。负载均衡器位于客户端和服务器之间&#xff0c;根据预设的策略将请求分发到多个服务器上&#xff0c;以…

华为HarmonyOS地图服务 4 - 通过“地图相机“控制地图的可见区域

场景介绍 华为地图的移动是通过模拟相机移动的方式实现的,您可以通过改变相机位置,来控制地图的可见区域,效果如图所示。 本章节将向您介绍相机的各个属性与含义,并移动相机。 相机移动前 接口…

基于lnmp搭建wordpress

一、案例目标 &#xff08;1&#xff09;了解LNMP环境的组成。 &#xff08;2&#xff09;了解LNMP环境的部署与安装。 &#xff08;2&#xff09;了解WordPress应用的部署与使用。 二、节点规划 IP 主机名 节点 192.168.200.20 lnmp lnmp服务节点 三、案例实施 LN…

基于微信小程序的购物系统+php(lw+演示+源码+运行)

基于微信小程序的购物系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的购物系统的开发全过程。通过分析基于微信小程序的购物系统管理的不足&#xff0c;创建了一个计算机管理基于微信小…