“这个shp的中文属性表快把我逼疯了。”
1 介绍
之前写的shp文件转换为KML文件,其实默认了shp文件的坐标系为wgs84。
因为KML是google开发的,而google earth只支持WGS84坐标系,所以,写入KML文件的数据必须是WGS84坐标系的数据。
最近遇到这个情况。
2 初步思路
这个情况有解决办法,检测输入文件是否是84坐标,如果不是,则先生成一个WGS84坐标的中间文件(也是shp格式),然后将这个中间文件转为KML格式。
arcgis它应该也是这样做的,只是具体的处理细节,美国人不会暴露出来给我们。但是但是,从结果倒推,acrgis大概率也是这样的处理流程。
首先检测shp是否是WGS1984坐标系。这里的检测很简单,判断WGS84的字符串是否在矢量文件的WKT中就可以实现了(思路很简单,但是存在一定的漏洞)
代码如下:
def check_is_84(file):
ds = ogr.Open(file)
layer = ds.GetLayer()
spatial_ref = layer.GetSpatialRef()
wkt = spatial_ref.ExportToPrettyWkt()
if 'WGS_1984' in wkt:
return True
else:
return False
那非wgs84的矢量文件如何转为WGS84坐标呢?
其实之前写过类似内容。
矢量文件坐标转换:2000坐标系转换为wgs84坐标系,具体代码实现
3 中文乱码
至此,一切都很顺利。但是,但是...
在上面的矢量文件的坐标转换的代码,我们使用了gdal.VectorTranslate函数,这个函数对中文不友好!
在QGIS打开转换后的shp,它的属性表如下:
再放大一点:
这个属性表原先是中文的,现在变为乱码了。
这也是shp文件的缺点。虽然shp文件很好用,但是因为这样那样的不舒服感,使我吐槽过shp file,并且在个人使用的角度上批判过shp格式的丑陋。
为什么看好Geopackage而不是shapefile或Geojson
shp格式把数据分开存储,坐标点数据存放在.shp中,属性表的数据放在.dbf中,有时候二者的数量对不上直接打不开shp文件。之前写过怎么修复破损的shp
4 解决思路
那现在怎么会变成乱码了呢?
经过一番排查,如果属性表数据存在中文,则gdal.VectorTranslate会把属性表数据以ISO-8859-1的编码方式存放在,dbf中
在QGIS右击转换后的shp文件,点击属性,点击Source,可以查看。
如果想单个文件的将乱码修复,则点击上面的按钮,选择GBK,然后再点击应用即可。
我们rstool处理工具,为了适配中文的属性表,必须要用编程的方法实现修复乱码问题,
这里主要关注的是.shp, .shx(索引文件)以及.dbf(数据表文件)这三个文件,因为这些是构成一个Shapefile的主要部分。
.shp, .shx是二进制文件,与编码无关。而dbf文件是我们重点的关注对象。
在坐标系转换前,我们把属性表信息读取出来,以字典的形式进行存储。等坐标系转换完成后,再把这些属性表赋予回去shp文件。
这里要判断dbf的编码格式,gbk、utf8或者其他。
我们更新一下shp转为kml的流程图,整体处理流程如下:
所以我们需要更改原先的shp2kml代码,原先的代码是直接利用ogr读取shp,顺带获取属性表数据。
如果dbf的编码是GBK,则使用dbfread库读取dbf文件;
如果dbf的编码是GBK,则改为ogr读取shp,
如果是其他类型,则不支持中文属性表,不更新保持空白。
最后将属性表赋予给kml文件
测试数据如下:一个2000坐标系的矢量文件在QGIS打开如下所示:
属性表如下:
在rstool处理完成时如下:
输入结果保存在输入结果所在的文件夹。
输入结果在google earth 打开如下。
中文属性表测试:
柏林:
至此,rstool支持不同坐标系的矢量文件转换为KML文件,且支持中文的属性表,确保中文不乱码。
今天先到这里了,如果需要rstool,还是老规则,在后台回复rstool获取链接。