为什么ArcGIS 10.3导出 Shapefile的字段名会被截断成3个汉字?低版本中不是至少可以存储4个汉字吗?
原因
这个问题仍然与编码类型有关。
ArcGIS 10.2 以及更早的版本,ArcGIS写shapefile的时候,遇到中文默认使用Windows当前语言 字符集编码(也称 代码页/CodePage/OEM CodePage),例如中文一般使用的是 CodePage 936(GBK)。
ArcGIS 10.2.1 以及之后的版本,ArcGIS写shapefile的时候,默认使用的是 UTF-8 编码类型。
这两种编码类型存储汉字所使用的字节数是不相同的,上面的关键字中我也给出了 wiki 的链接,有兴趣点进去看看详情。简言之,shapefile自身的限制是字段为9个字节,CP936编码下汉字通常为双字节存储,因此可以存储 9/2=4 个汉字;UTF-8 编码下汉字至少需要3个字节存储,因此最多只能存储 9/3=3 个汉字了。
<ignore_js_op>
举个例子,在Python命令行中,我们求一下 Unicode字符串的长度就可以真相大白。
<ignore_js_op>
解决方法
Perfect Solution:
使用地理数据库,放弃shapefile,避免各种截断问题,这也是存储地理数据的康庄大道。
但是,shapefile的拥趸说“我的需求是恢复以前存储4个汉字的shapefile,我不想用地理数据库,我希望得到老版本的shapefile的结果,我不在乎shapefile的编码类型是什么 ……bla bla……”好吧,方法还是有的。
Workaround:
这里还有个注意事项: 如果你用的刚好是 10.2.1 和10.2.2 这两个版本,那么要打补丁后以下设置才生效。以前写过另外一篇,详情点 这里。 如果你用的是 10.3.x ,那么直接向下进行。
1.打开注册表,定位到 ‘My Computer\HKEY_CURRENT_USER\Software\ESRI\Desktop 10.x’<li>创建项 ‘Common‘, 接着在其下创建 ‘CodePage’ 项, 添加 ‘字符串’,名称: dbfDefault,健值:oem(或者 936)。
<ignore_js_op>
这样ArcGIS Desktop 读、写 shapefile的默认方式就将是Windows当前语言 OEM CodePage 936。
PS: 当然这种方法,也可以解决第一个问题,并且不需要为缺失oem编码信息的数据增加cpg文件了。两种方法,任君选择。
===================================
操作方法:读写在不同代码页编码的 shapefile 和 dBASE 文件
摘要
Esri 在 ArcGIS for Desktop(ArcMap、ArcCatalog 和 ArcToolbox)中执行了一个“代码页转换”功能,该功能允许桌面应用程序读写在不同代码页编码的 shapefile 和 dBASE 文件。 可在系统注册表内指定代码页值,以激活 dBASE 文件的代码页转换功能(名为“dbfDefault”)。 此功能与 ArcInfo Workstation 中的 &CODEPAGE 功能十分相似。
ArcGIS 10.2.1 之前的版本,可使用以下程序设置所需的代码页行为。 如果安装了 ArcGIS for Desktop 10.2.1 或 10.2.2,在遵循以下说明前,请下载并安装知识库文章 42646 所描述的修补程序。
注: 在每个 shapefile (.DBF) 的标题中都包含了对某一代码页的引用。 ArcGIS 10.2.1 之前的版本,所用的代码页与用户的区域设置相对应。 例如,如果用户位于日本地区,则 .DBF 文件所使用的代码页将为 'Shft-JIS’。 在 ArcGIS 10.2.1 版本中,系统默认将 shapefile (.DBF) 中的代码页设置为 UTF-8 (UNICODE)。 这与现有的国际化活动相一致,并应保证数据可读。
常见问题解答
dbfDefault 设置有何用处?
在系统注册表内设置一个代码页值后,用户即可读写在该页中编码的 shapefile 和 dBASE 文件。 例如,用户可以在 OEM 中设置代码页注册表值,以导出在 OEM 中编码的 shapefile。 此外,用户还可读取文件中未存储代码页信息的 shapefile 和 dBASE 文件,前提是用户知道文件在哪个代码页中编码。
为什么要设置 dbfDefault?
在 ArcGIS Desktop 中打开 shapefile 和 dBASE 文件时,Desktop 程序会查看 dBASE 文件标题上的“语言驱动程序 ID”(LDID) 或者相关的 *.CPG 文件,以确定代码页并决定读取文件的哪个代码页。 如有必要,ArcGIS for Desktop 会基于检索到的代码页信息,通过代码页转换功能显示相应的字符串。 如果 dBASE 文件缺少 LDID 或者 .CPG 文件,则假设文件在 Windows (ANSI/Multi-byte) 代码页中编码。
如果 Desktop 程序读取在 OEM 中编码的 dBASE 文件,但文件中不包含任何代码页信息或不包含 LDID 或 CPG 文件,则字符无法正确显示。 这是因为 Desktop 程序无法找到代码页信息,所以假定文件是在 ANSI 代码页中编码的,而文件实际上是在 OEM 中编码的。 这表示 ArcGIS 将 OEM 文件视为在 ANSI 中编码,所以导致储存在文件中的 8 位字符显示不正确。
大多数 shapefile 和 dBASE 文件应将代码页信息存储在文件中。 Microsoft Access 2000 和 Excel 2000 等程序将 dBASE 文件编码于 OEM 中,但不包含 LDID 中的代码页信息,所以 ArcGIS 无法正确读取文件。 要避免此类问题,用户在打开缺少代码页信息的文件之前,可以为适当的代码页设置 dbfDefault。
dbfDefault 的工作原理是什么?
需要注意的是,有一种情况是例外:从 ArcCatalog 和 ArcToolbox 中的 coverage 导出的 shapefile,除了西班牙语和阿拉伯语的文件之外,都是在 OEM 中编码的,无论 dbfDefault 设置是什么。 这是因为 ArcToolbox 中的“将 coverage 转换为 shapefile”用作 ArcInfo Workstation 的功能,而后者定义的是 DOS 上运行的图层,因此输出文件总是在 OEM 代码页或 DOS 代码页中进行编码。 从 ArcCatalog 和 ArcToolbox 的 coverage 中导出的西班牙语和阿拉伯语的 shapefile 文件在 ANSI 中编码。 从 ArcCatalog 和 ArcToolbox 的 coverage 中导出的 shapefile 文件总是位于 OEM 代码页中(西班牙语文件除外)
同样的逻辑也适用于在 ArcGIS for Desktop 中读取的 shapefile 和 dBASE 文件;如果 shapefile 或 dBASE 文件缺少 LDID 或 .cpg 文件,ArcGIS 则假定要编码的文件位于 dbfDefault 定义的代码页中。 例如,如果 dbfDefault 值被设置为 OEM,而 dBASE 文件缺少 LDID 和 .cpg 文件,ArcGIS for Desktop 则假定文件是在 OEM 中编码的,因此执行代码页转换来显示 ArcMap 和 ArcCatalog 中的8位字符(因为这两个应用程序都是使用 ANSI 代码页来显示字符串的 Windows 程序)。
注: 如果用户将 dbfDefault 值设置为某个代码页,那么在 ArcGIS 中导出的所有 shapefile 和 dBASE 文件都将编码在该代码页中。 所有不具备代码页信息的 shapefile 和 dBASE 文件也都假定位于该代码页中。 因此,当任务完成时,将 dbfDefault 值设置回默认值(无值)十分重要。dbfDefault 适用于哪些程序?
ArcGIS for Desktop 是唯一一个受到 dbfDefault 设置影响的程序。 其他程序(例如 ArcInfo Workstation 和 ArcView 3.x)或其他代码页设置(例如 ArcInfo Workstation 中的 '&CODEPAGE' 功能和 ArcView 3.x 中的“代码页配置文件”)都不受影响。
在 ArcInfo Workstation 中:
- 带有 &CODEPAGE OEM 的 ARCSHAPE 可在 OEM 中创建 shapefile
- 带有 &CODEPAGE ANSI 的 ARCSHAPE 可在 ANSI 创建 shapefile
- 带有 &CODEPAGE OEM 的 INFODBASE 可在 OEM 中创建 dBASE 文件
- 带有 &CODEPAGE ANSI 的 INFODBASE 可在 ANSI 中创建 dBASE 文件
- Shapefile 和 dBASE 文件保存在 ANSI 代码页中。
受 dbfDefault 影响的数据格式有哪些?
Shapefile 和 dBASE 文件是唯一可供 dbfDefault 设置用于指定代码页的数据格式。 其他数据格式,例如 coverage 和个人地理数据库,不会受到 dbfDefault 设置的影响。
在 ArcGIS for Desktop 中(无论 dbfDefault 设置如何):
- 个人地理数据库保存在 Unicode 中
- 个人地理数据库表保存在 Unicode 中
- coverage 保存在 ISO 代码页中
- INFO 文件保存在 ISO 代码页中
- 交换文件保存在 ANSI 代码页中
- 文本文件保存在 ANSI 代码页中
过程
给出的说明描述了如何在系统注册表中设置 dbfDefault 值。 下面列出两个选项。
警告: 下面的说明涉及更改操作系统的重要组成部分。 建议您先备份操作系统及文件(包括注册表),然后再继续操作。 必要时,请咨询合格的计算机系统专业人士。 您按照下列步骤进行操作期间,Esri 无法防止错误更改造成的结果;因此,请谨慎操作并自行承担风险。
选项 A
- 在系统注册表中添加两个名为“Common”和“CodePage”的项。
如需添加项:- 打开注册表编辑器:单击“开始”>“运行”,输入“regedit”,然后单击“确定”。
- 在注册表树中(位于注册表窗口左侧窗格中),转至“My Computer\HKEY_CURRENT_USER\Software\ESRI”,然后单击注册表项,“Desktop 10.x”。 对于 Pro,单击注册表项“Pro1.0”。 (对于 9.3.1 版本或更早版本,转至“My Computer\HKEY_CURRENT_USER\Software', and click the registry key ESRI”。)
- 添加一个名为 Commom 的新项(在“编辑”菜单中:
导航到“新建”,选择“项”,输入名称“Common”,并按 Enter 键)。 - 单击刚刚创建的注册表项(公共),并添加一个名为“CodePage”的新项。
- 将一个新的字符串值“dbfDefault”添加到 CodePage 项中。
添加字符串值:- 单击“CodePage”项。
- 在“编辑”菜单中,导航到“新建”,然后选择“字符串值”。
- 键入'dbfDefault’作为新的值,并按“ENTER”键。
新的“CodePage”项应如下显示:
- 输入一个代码页值。
- 选择刚刚添加的条目;重要的是选择 dbfDefault,而不是 (Default)。
- 在“编辑”菜单中,单击”修改”。
- 在“值”数据中,键入新的代码页值,并单击“确定”。
下表所示为支持的代码页标识符(不区分大小写)。
- OEM 代码页标识符
437 - 美国
708 - 阿拉伯语 (ASMO 708)
720 - 阿拉伯语 (Transparent ASMO),阿拉伯语 (DOS)
737 - 希腊语,希腊语 (DOS)
775 - 波罗的海语,波罗的海语 (DOS)
850 - 多语言拉丁语 1,西欧语言 (DOS)
852 - 拉丁语 2,中欧语言 (DOS)
855 - 西里尔语
857 - 土耳其语,土耳其语 (DOS)
860 - 葡萄牙语,葡萄牙语 (DOS)
861 - 冰岛语,冰岛语 (DOS)
862 - 希伯来语,希伯来语 (DOS)
863 - 加拿大法语,加拿大法语 (DOS)
864 - 阿拉伯语,阿拉伯语 (864)
865 - 北欧语言,北欧语言 (DOS)
866 - 俄语,西里尔语 (DOS)
869 - 现代希腊语,现代希腊语 (DOS)
932 - 日语,日语 (Shift-JIS)
936 - 中文(简体):中华人民共和国,新加坡
949 - 韩语(统一的韩语代码)
950 - 繁体中文:台湾,香港,中华人民共和国
ALARABI - 将代码页设置为 448
- ANSI 代码页标识符
1250 - 中欧语言
1251 - 西里尔语
1252 - 西欧语言
1253 - 希腊语
1254 - 土耳其语
1255 - 希伯来语
1256 - 阿拉伯语
1257 - 波罗的海语
1258 - 越南语
Big5 - 汉语:台湾、香港、澳门
SJIS - 日语(将代码页设置为 932)
- ISO 代码页标识符
88591 - 拉丁语 1:西欧语言
88592 - 拉丁语 2:中欧和东欧语言
88593 - 拉丁语 3:南欧语言
88594 - 拉丁语 4:北欧语言
88595 - 西里尔语
88596 - 阿拉伯语
88597 - 希腊语
88598 - 希伯来语
88599 - 拉丁语 5:土耳其语
885910 - 拉丁语 6:北欧语言
885911 - 泰语
885913 - 立陶宛语
885915 - 拉丁语 9:西欧语言(拉丁语 1 升级版)
- Unicode 值
UTF-8 - 将代码页设置为 65001
UTF8 - 将代码页设置为 65001
注: 现在 Shapefile 可储存至 UTF-8。 然而,仅 ArcGIS for Desktop 可识别以 UTF-8 编码的 shapefile。
选项 B
或者,用批处理文件修改 Windows 注册表。
- 在记事本中,使用以下编码创建文件 ChangeCodePage.bat:
编码: @ECHO OFF IF "%1"=="" GOTO :EOF reg add HKEY_CURRENT_USER\Software\ESRI\Desktop10.3\Common\CodePage /v dbfDefault /t REG_SZ /d %1 /f
注: 更改路径,以匹配要修改的系统上的 ArcGIS 版本,例如,\Desktop10.1)。
- 将文件保存到要修改的计算机上的某个位置。
- 打开命令提示符窗口(可能需要“以管理员身份运行”以执行批处理文件)。
- 要执行批处理文件(在本例中,将代码页更改为日语),请导航到批处理文件所在位置并运行以下命令:
ChangeCodePage SJIS
此时注册表项已完成创建,且代码页已设置为 SJIS。