分享

Shapefile 中文乱码与字段名字符截断问题分析和解决方法

 Jcstone 2021-12-06

一、关于shapefile

        关于shapefile的局限性,可以参考这篇文章:https://blog.csdn.net/yaoxiaochuang/article/details/52465335

        Shapefile是创建于上个世纪90年代的数据格式,由于它开放易用至今仍然倍受欢迎。Shapefile文件是描述空间数据的几何和属性特征的非拓扑实体矢量数据结构的一种格式,由ESRI公司开发。

一个Shapefile文件最少包括三个文件:

        1.主文件(*.shp)、--存储地理要素的几何图形的文件。

        2.索引文件(*.shx)、--存储图形要素与属性信息索引的文件。

        3.dBASE表文件(*.dbf),--存储要素信息属性的dBase表文件。

       主文件是一个直接存取,变长记录的文件,其中每个记录描述一个实体的数据,称为shape。在索引文件中,每个记录包含对应主文件记录离主文件头开始的偏移量。dBASE表文件包含各个实体的属性特征记录。几何和属性间的一一对应关系是基于一个不重复的记录顺序代码来实现的,在dBASE表文件中的属性记录和主文件中的记录是相同顺序的。

除此之外还有可选的文件包括:

        4.空间参考文件(*.prj)、

        5.几何体的空间索引文件(*.sbn 和 *.sbx)、

        6.只读的Shapefiles的几何体的空间索引文件(*.fbn 和*.fbx)、

        7.列表中活动字段的属性索引(*.ain 和 *.aih)、

        8.可读写Shapefile文件的地理编码索引(.ixs)、

        9.可读写Shapefile文件的地理编码索引(*.mxs)、

       10.dbf文件的属性索引(*.atx)、

       11.以XML格式保存元数据(*.shp.xml)、

        12.用于描述.dbf文件的代码页,指明其使用的字符编码的描述文件(*.cpg)。

详情可以参考这篇文章:shapefile的数据结构

二、Shapefile中文乱码问题

        ArcGIS10.2之后的桌面版本ArcMAP打开之前保存的Shapefile文件,总会不时遇到中文字符出现乱码现象,这是因为新旧版本的默认编码规则变化导致:

        ArcGIS10.2.1之前版本,Shapefile根据Locale进行编码,即注册表中的My Computer\HKEY_CURRENT_USER\Software\ESRI\Desktop 10.x\下的common—codepage—dbfDefault

        ArcGIS10.2.1及之后版本,Shapefile一般是utf-8编码,ArcGIS会先读取DBF头文件LDID中的编码,然后是CPG文件,最后是CodePage。

三、解决方法

        中文出现乱码的根本原因是读取文件使用的编码类型和文件实际存储的编码类型不一致。

        在ArcGIS Desktop 生产 shapefile 数据中,头文件(dBase Header)中,一般会包含shapefile使用的编码类型的信息,即 LDID ( Language Driver ID),它告诉应用程序用何种编码类型去正确读取它。

        在Shapefile的子文件中,有时我们还会发现同名 *.cpg 文件,文件中也存储了编码信息,用记事本打开,看到例如UTF-8。

        二者被ArcGIS 识别的优先顺序是,LDID 优先于 CPG文件。

        shapefile是开放格式,只要了解了数据规范,完全可以脱离ArcGIS生产数据。在Windows中文语言设置下,假设你自己写代码或者使用第三方的程序生产了shapefile,默认使用 CP936(GBK)编码存储,忘记在数据头文件中约定—— “我用了936!”。如果是 ArcGIS 10.2之前的版本,那么没问题,ArcGIS 默认就是以这种方式识别,不会出现中文乱码。如果用高于 ArcGIS 10.2的版本打开这个shapefile,中文就会出现乱码,因为在缺失 LDID 和 CPG时,ArcGIS默认使用 UTF-8 来读取 shapefile。

        在shapefile文件里创建个记事本,修改为同名的*.cpg 文件,文本内容oem或者936。

四、如何检测shapefile是用什么编码

        如果不知道Shapefile的编码类型,可以使用程序检测:

        共享别人写的一个python代码:

import struct

dbf = 'D:\tShapefiles\test.dbf'

dat = open(dbf, 'rb').read(30)[29:]

id = struct.unpack('B', dat)[0] 

print(id, hex(id))

例如,得到这样的打印结果:

[b](77, '0x4d')[/b]

通过这样的 ID 到     编码表     中查到就是 CodelPage 936。

五、ArcGIS 10.3 Shapefile的字段名截断问题

        ArcGIS 10.3导出 Shapefile的字段名会被截断成3个汉字?低版本中不是至少可以存储4个汉字吗?

         这个问题仍然与编码类型有关。

        ArcGIS 10.2 以及更早的版本,ArcGIS写shapefile的时候,遇到中文默认使用Windows当前语言字符集编码(也称代码页/CodePage/OEM CodePage),例如中文一般使用的是CodePage936(GBK)。

        ArcGIS 10.2.1之后的版本,ArcGIS写shapefile的时候,默认使用的是 UTF-8 编码类型。

        这两种编码类型存储汉字所使用的字节数是不相同的, shapefile自身对字段的限制是9个字节,CP936编码的汉字通常为双字节,因此可以存储 9/2=4 个汉字;UTF-8 编码下汉字至少需要3个字节存储,因此最多只能存储 9/3=3 个汉字了。

        解决方法:

        一是使用地理数据库(GDB,SDE),放弃shapefile,避免各种截断问题。

        二是让arcgis默认用CP936编码,

    打开注册表,定位到 'My Computer\HKEY_CURRENT_USER\Software\ESRI\Desktop 10.x’<li>创建项 'Common', 接着在其下创建 'CodePage’ 项, 添加 '字符串’,名称: dbfDefault,健值:oem(或者 936)。

        修改完注册表之后,必须新建一个Shape文件或将已有的另存为(Export Data)新的Shape文件,才能让前面的修改生效。

        这样ArcGIS Desktop 读、写 shapefile的默认方式就将是Windows当前语言 OEM CodePage 936。    

————————————————

版权声明:本文为CSDN博主「aganliang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/aganliang/article/details/80993406

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多