GDAL C#读取shp中文属性值乱码问题
2017-01-05 18:10
477 查看
GDAL的C#版本读取shp中,如果属性值中含有中文,读出来有可能是乱码的问题,根据SWIG生成的C#代码调试发现问题所在,在Ogr.cs文件中有这么一个函数,代码如下:
问题就出现在上面这句中,如果shp文件中dbf的编码是utf-8的时候,pNativeData实际上就是GDAL库读取到的一个const char*的地址,这个时候,使用Marshal.PtrToStringAnsi函数返回的长度会变小,下面举个栗子:
如果GDAL的C++库返回的const char* pszValue = “中”,那么pNativeData的值实际上就是pszValue这个地址,且用UTF8编码的时候,pszValue指针对应的内存中的信息应该是”E4 B8 AD 00 XX XX”,后面的XX表示其他的东西,只有前四个有用。
这时pNativeData的值就是上面这个”E4 B8 AD 00 XX XX”字符串的地址,调用下面这句,返回的值居然是2。明明一个3的字符串为啥长度是2,就因为这里长度变短,导致后面转string的时候丢失了信息,造成了乱码。
本来想试下Marshal.PtrToString其他的函数,结果发现Marshal.PtrToStringAuto和Marshal.PtrToStringUni返回的长度都是16,就更不对了,没办法,用了一个笨办法,写了个循环来查找长度。修改后的代码如下:
同理,将Gdal.cs、Osr.cs这两个文件里面的这个函数也修改,重新编译即可解决这个问题。
最后,如果与shp中dbf的编码使用GBK之类的编码,请设置SHAPE_ENCODING这个配置项,如果shp文件夹中有同名的cpg文件则可以不用设置,但是确保cpg文件中写的编码与dbf中的实际编码相对应。
internal static string Utf8BytesToString(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return null; int length = Marshal.PtrToStringAnsi(pNativeData).Length; //问题在这句 byte[] strbuf = new byte[length]; Marshal.Copy(pNativeData, strbuf, 0, length); return System.Text.Encoding.UTF8.GetString(strbuf); }
问题就出现在上面这句中,如果shp文件中dbf的编码是utf-8的时候,pNativeData实际上就是GDAL库读取到的一个const char*的地址,这个时候,使用Marshal.PtrToStringAnsi函数返回的长度会变小,下面举个栗子:
如果GDAL的C++库返回的const char* pszValue = “中”,那么pNativeData的值实际上就是pszValue这个地址,且用UTF8编码的时候,pszValue指针对应的内存中的信息应该是”E4 B8 AD 00 XX XX”,后面的XX表示其他的东西,只有前四个有用。
这时pNativeData的值就是上面这个”E4 B8 AD 00 XX XX”字符串的地址,调用下面这句,返回的值居然是2。明明一个3的字符串为啥长度是2,就因为这里长度变短,导致后面转string的时候丢失了信息,造成了乱码。
int length = Marshal.PtrToStringAnsi(pNativeData).Length; //length = 2
本来想试下Marshal.PtrToString其他的函数,结果发现Marshal.PtrToStringAuto和Marshal.PtrToStringUni返回的长度都是16,就更不对了,没办法,用了一个笨办法,写了个循环来查找长度。修改后的代码如下:
internal static string Utf8BytesToString(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return null; int nMaxLength = Marshal.PtrToStringAuto(pNativeData).Length; int length = 0;//循环查找字符串的长度 for(int i=0; i<nMaxLength; i++) { byte []strbuf1 = new byte[1]; Marshal.Copy(pNativeData+i, strbuf1, 0, 1); if(strbuf1[0] == 0) { break; } length++; } byte[] strbuf = new byte[length]; Marshal.Copy(pNativeData, strbuf, 0, length); return System.Text.Encoding.UTF8.GetString(strbuf); }
同理,将Gdal.cs、Osr.cs这两个文件里面的这个函数也修改,重新编译即可解决这个问题。
最后,如果与shp中dbf的编码使用GBK之类的编码,请设置SHAPE_ENCODING这个配置项,如果shp文件夹中有同名的cpg文件则可以不用设置,但是确保cpg文件中写的编码与dbf中的实际编码相对应。
相关文章推荐
- GDAL C#读取shp中文属性值乱码问题
- GDAL读取S-57海图数据中文属性值乱码问题解决(续)
- GDAL读取S-57海图数据中文属性值乱码问题解决
- GDAL读取S-57海图数据中文属性值乱码问题解决
- GDAL读取S-57海图数据中文属性值乱码问题解决(续)
- 关于php读取中文乱码问题
- 关于C++ Builder 和 Dephi读取文本文件TXT出现中文乱码的问题
- C# 从剪贴板中读取HTML中的中文字符出现乱码问题的解决方案
- Java读取文件 解决中文乱码问题
- Flex读取非UTF-8中文数据乱码问题的解决方案 flex中文乱码
- geoserver shp文件地图标注中文乱码问题
- 解决javascript读取中文cookie时的乱码问题
- Flex读取非UTF-8中文数据乱码问题的解决方案
- Flash读取XML文件的中文时出现乱码问题解决方法
- 解决使用Properties,读取中文乱码问题
- JavaScript读取中文cookie时的乱码问题的解决方法
- 中文读取中的乱码问题
- 读取文件时出现中文乱码问题的解决
- c#读取mysql的中文乱码问题
- js生成的cookie由asp.net读取的时候中文乱码问题的解决