项目场景:
在一次给县局做项目的过程中,发现县局对地块套合数据有非常深的执念。大部分都是非常简单的相交、计算面积、导出奥维、表格等等,极其琐碎。
相对来说政府人员对gis类软件接触较少且无专业基础,于是我就动了邪念,搞一个以开源gis库为基础的简单、无脑gis小工具。
该工具在去年已经写完了,近期进行维护修改的时候发现了一个非常棘手的问题,记录一下
问题描述
我在工具中的相交及标识函数中使用了geopandas来读取shp数据,并强制utf-8来输出。
gdf = gpd.read_file(result)
gdf2 = gpd.read_file(result2)
....
res4.to_file(out, driver="ESRI Shapefile", encoding="utf-8")
问题就出在这里,因为存在部分shp数据缺少cpg文件,无法知道它的编码方式 在默认使用utf-8来encoding的时候会出现乱码,无法写入数据。报错:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 59
为此,我第一个采用办法就是强制读取及输出的时候使用gbk,并修改所有utf-8为gbk,并新增:
os.environ["SHAPE_ENCODING"] = "GBK"
fiona.supported_drivers['ESRI Shapefile'] = 'raw'
但是在我测试后发现依然出现
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 59: invalid start byte
怀疑是否编码不对,新增自动检测:
import chardet
......................
if not os.path.exists(dbf_path):
logger.warning(f"{dbf_path} 不存在")
return None
try:
with open(dbf_path, "rb") as f:
raw_data = f.read(20000)
result = chardet.detect(raw_data)
encoding = result["encoding"]
confidence = result["confidence"]
# 如果置信度低于 50%,说明识别不可靠
if confidence < 0.6:
logger.warning(f"{dbf_path} 编码识别不可靠(置信度 {confidence:.2f}),尝试 fallback 到 gbk")
return 'gbk'
logger.info(f"检测到 {dbf_path} 的编码为: {encoding} (置信度 {confidence:.2f})")
return encoding
except Exception as e:
logger.error(f"检测 {dbf_path} 编码失败,使用 fallback 编码 gbk,错误信息:{e}")
return 'gbk'
测试后
执行dataidentity函数出错,错误信息为'utf-8' codec can't decode bytes in position 8-9: unexpected end of data
于是多处打印分析,发现shp数据可以在gbk下正确读取,应该是正确的编码方式并且适用于大多数情况,但是为什么在强制指定后依然报utf-8的错误呢
原因分析:
至现在尚未发现原因,不知道该如何从源头解决
解决方案:
目前最简单的办法就是在出现decode问题后,把dbf文件用记事本打开并保存为utf-8,即可使用。
如有大佬看到,知道什么原因,请留言。万分感谢!!!!!