目录

 

从ArcGIS10.2开始,只要是属性表编码与.cpg文件记录的编码方式一致,就不会再有显示乱码的问题。网上查询到的修改注册表的方法,我在ArcGIS10.2中试过,似乎已经不再起效了。

那么对于没有.cpg或者的情况,应该可以看属性表.dbf文件。如果编码方式正确,这个文件用文本编辑器打开是可以看到正常的中文的:

 

在正常显示中文情况下,可以查看下文件的编码方式:

 

当然,如果遇到乱码,可以尝试用别的编码方式打开,这样你就能知道属性表具体是什么编码了。对于国内的情况来说,只有ANSI编码和UNICODE编码两种:其中简体中文系统中ANSI编码就是GB2312编码;UTF-8是UNICODE编码的一种具体实现。

1.2. 设置读取的编码方式

1.2.1. GDAL设置

可以通过全局设置函数CPLSetConfigOption(),来配置读取Shp文件的读取编码。例如对于简体中文系统中ANSI编码,可以设置为GBK:

CPLSetConfigOption("SHAPE_ENCODING","GBK");

上面这种方式是全局设置的,如果想设置单个文件的编码方式也是可以的。例如,打开一个矢量文件读取为UTF-8的数据集:

char** ppszOptions = NULL; ppszOptions = CSLSetNameValue(ppszOptions, "ENCODING", "UTF-8"); GDALDataset *poDS = (GDALDataset*)GDALOpenEx(filePath.c_str(), GDAL_OF_VECTOR, NULL, ppszOptions, NULL);

网上提供的解决方案都是将编码方式设置为空[1],这种方式应该更具有通用性,起码我这里读取GBK和UTF-8格式的Shp的格式都是可以的:

CPLSetConfigOption("SHAPE_ENCODING","");

1.2.2. 解码方式

如果读取出来的字段属性仍然是乱码,就应该考虑字符串的解码问题,就是获取的字段属性字符串没有正确的解码出来。例如读取UTF-8的Shp文件的属性字段:

OGRFeature *poFeature; while ((poFeature = poLayer->GetNextFeature()) != NULL) {     OGRGeometry *pGeo = poFeature->GetGeometryRef();     OGRwkbGeometryType pGeoType = pGeo->getGeometryType();      //           OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();     int n = poFDefn->GetFieldCount(); //获得字段的数目,不包括前两个字段(FID,Shape);     for (int iField = 0; iField <n; iField++)     {         //输出每个字段的值         //cout << poFeature->GetFieldAsString(iField) << "    ";         cout << UTF8_To_string(poFeature->GetFieldAsString(iField)) << "   ";                }     //cout << endl;         OGRFeature::DestroyFeature(poFeature); }

默认情况下,cout是无法正确打印输出UTF-8字符编码的,通过UTF8_To_string这个函数,将UTF-8编码的字符串转换成本地ANSI编码,也就是GBK编码字符串,就可以正确输出显示了。附带一下两者的转换函数[2]

// UTF8转std:string // 转换过程:先将utf8转双字节Unicode编码,再通过WideCharToMultiByte将宽字符转换为多字节。 std::string UTF8_To_string(const std::string& str)  {      int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);      wchar_t* pwBuf = new wchar_t[nwLen + 1];    //一定要加1,不然会出现尾巴      memset(pwBuf, 0, nwLen * 2 + 2);      MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);      int nLen = WideCharToMultiByte(CP_ACP,