Shapefile 属性表中文全是乱码,几何却完全正常
边界线画得一丝不差,属性弹窗里的地名却是「鍖椾含甯傚湴鍥炬」。
现象
打开 districts.shp,几何位置正确,
属性表里的 NAME 字段显示为 鍖椾含甯傚湴鍥炬,
另一份文件显示为 ?????。
ogr2ogr 转换时控制台报
Warning 1: One or several characters couldn't be converted correctly from UTF-8 to ISO-8859-1。
原因
Shapefile 的 .dbf 本身不记录编码。GDAL 判断顺序是:
先看有没有 .cpg 文件,再看 .prj 里的 ENCODING,
最后退回系统默认代码页。
鍖椾含 是典型的 UTF-8 字节被按 GBK 解读的结果:
「北京」的 UTF-8 是 E5 8C 97 E4 BA AC,
每两字节按 GBK 解码就成了三个生僻汉字。
反过来,GBK 字节被按 UTF-8 解码则会出现 ????? 或替换符。
| 实际编码 | 被按什么读 | 典型表现 |
|---|---|---|
| UTF-8 | GBK | 鍖椾含甯傚湴鍥炬(生僻字成串) |
| GBK | UTF-8 | 问号、方块或替换符 |
| GBK | Latin-1 | 丠这种双字节乱码 |
排查过程
- 检查 shapfile 同目录下有没有
.cpg文件,内容应为UTF-8或GBK。 - 用十六进制看一个已知汉字的字节。三个字节且首字节
E4~E9是 UTF-8,两个字节且首字节B0~F7是 GBK。 - 用
ogrinfo -al输出几个字段值,确认乱码规律。 - 用检测工具对
.dbf跑一次编码猜测,不要靠肉眼看。
# 查看 dbf 编码声明
ogrinfo -al -so districts.shp | Select-String -Pattern "Encoding"
# 用 chardet 检测
python -c "import chardet;print(chardet.detect(open('districts.dbf','rb').read(20000)))"
# {'encoding': 'GB2312', 'confidence': 0.99}
解决方案
补一个 .cpg 文件是最省事的做法,不改动数据本身。
需要统一到 UTF-8 时用 ogr2ogr 重写。
# 方案一:写 .cpg 声明实际编码(GBK)
Set-Content -Path districts.cpg -Value "GBK" -Encoding ASCII
# 方案二:整体转成 UTF-8,同时生成 .cpg
ogr2ogr -f "ESRI Shapefile" out districts.shp -lco ENCODING=UTF-8
# 方案三:GeoJSON 输出时指定源编码
ogr2ogr -f GeoJSON districts.geojson districts.shp -lco ENCODING=GBK
前端用 shapefile.js 解析时,直接传 encoding 参数,
不要依赖库的自动推断。
const source = await shp('/data/districts.shp');
const dbffile = await dbf('/data/districts.dbf', { encoding: 'gbk' });
const geojson = new GeoJSON(source, { dbffile });
验证
属性表中的 NAME 应显示为「北京市」,长度与原始记录一致;
随机抽 20 条,全部可读,无问号与替换符。
SELECT NAME, length(NAME) FROM districts LIMIT 5;
-- 北京市 | 3
-- 天津市 | 3
# 命令行快速核对
ogrinfo -al districts.shp | Select-String "NAME" | Select-Object -First 3
适用版本
| 工具 / 库 | 版本 | 说明 |
|---|---|---|
| GDAL / ogr2ogr | 3.6 及以上 | 优先读 .cpg,其次读系统代码页 |
| QGIS | 3.28 及以上 | 图层属性里可手动指定编码 |
| shapefile.js | 6.x | DBF 需显式传 encoding |
| ArcGIS Pro | 3.x | 默认按 UTF-8 写,旧数据需登记代码页 |
经纬志(2026)。《Shapefile 属性表中文全是乱码,几何却完全正常》。https://www.jingweizhi.com/cookbook/shp-gbk-garbled.html(访问日期 2026-11-03)。