在GeoServer中文社区的讨论地址为:http://opengeo.cn/bbs/read.php?tid=1701&page=e&#a

使用geotools修改shapefile之后, 发现dbf文件内容中, 属性名都成了乱码, 但属性值就不是乱码。修改之前还没有乱码的。
而且在代码中也已经通过以下方式设置过编码方式了:

ShapefileDataStore shape = new ShapefileDataStore(url);
shape.setStringCharset(Charset.forName("GBK"));

我的修改代码如下:

    /**
* 修改shapefile.
* @param dataStore
* @param fidStr 要修改的数据对应的featureID
* @return
*/
public static boolean updateShapeFile(ShapefileDataStore dataStore,String fidStr)
{
DefaultTransaction transaction = null;
SimpleFeatureStore store = null;
try {
dataStore.setStringCharset(Charset.forName("GBK"));
String[] featureNames = dataStore.getTypeNames();
String featureName = featureNames[0];
// 创建默认的事务对象
transaction = new DefaultTransaction(); // 同时标明数据源使用的要素名称,通常Shapefile文件名称和Shapefile类型名称通常是一样的。
store = (SimpleFeatureStore) dataStore.getFeatureSource(featureName);
// 关联默认事务和数据源
store.setTransaction(transaction);
//创建过滤器
FilterFactory2 ff = (FilterFactory2) CommonFactoryFinder.getFilterFactory2(null);
Set<FeatureId> fids = new HashSet<FeatureId>();
FeatureId fid = ff.featureId(fidStr);
fids.add(fid);
Filter filter = (Filter) ff.id(fids);
//根据过滤器对过滤的feature进行修改
store.modifyFeatures("资料表编号", "test", filter); // 提交
transaction.commit();
} catch (IOException e) {
e.printStackTrace();
try {
// 回滚
transaction.rollback();
} catch (IOException e1) {
e1.printStackTrace();
}
return false;
}finally{
if(transaction!=null){
// 关闭
transaction.close();
transaction = null;
}
}
return true;
}

经过定位发现问题出在transaction.commit();

而且shp文件的文件内容中也有汉字,但是没有出现乱码的问题,那么就从dbf文件的文件头着手。

查看geotools的源代码,发现对dbf文件的操作都在org\geotools\data\shapefile\dbf这个包下,其中类DbaseFileWriter实现的是对dbf文件的写操作,包括属性名(head)的写入和属性值(body)的写入,而head的写入在

    public DbaseFileWriter(DbaseFileHeader header, WritableByteChannel out, Charset charset)
throws IOException {
//写header
header.writeHeader(out);
。。。。。。
}

而writeHeader方法的定义在DbaseFileHeader这个类中.

原来的代码如下:

              // write the field name
for (int j = 0; j < 11; j++) {
if (fields.fieldName.length() > j) {
buffer.put((byte) fields.fieldName.charAt(j));
} else {
buffer.put((byte) 0);
}
}

意思就是,将属性名称以byte形式放到buffer中,一个属性名所占字节数不能超过11个,不足11个的用(byte)0补充。
关键就在(byte) fields.fieldName.charAt(j),对于汉字来说,占用两个字节,而这里从char转化成byte的时候除了问题.
就拿下面这个字符串来说:
        String str = "资";
        byte[] bytes = str.getBytes();
        for(int i=0;i<bytes.length;i++)
            System.out.println(bytes);
输出结果应该是:
        -41
        -54
        这里占用两个字节,是对的.
如果按照它里面的方法的话:
        char chars = '资';
        byte[] bytes = {(byte)chars};
        for(int i=0;i<bytes.length;i++)
            System.out.println(bytes);
输出结果是:
        68
        这里明显是不对的.
        
        就按照上面的逻辑,修改原代码如下(我这里只是方法,这段代码应该再优化一下):
          int j = 0;
        for(int counter=0; j<11&&counter<fields.fieldName.length(); counter++){
            char cha =  fields.fieldName.charAt(counter);
            String str = new String(cha+"");
            byte[] bytes = str.getBytes();
            for(int k=0;k<bytes.length;k++){
                buffer.put(bytes[k]);
                j++;
            }
        }
        if(j!=11){
            for(int k=0;k<(11-j);k++){
                buffer.put((byte) 0);
            }
        }

geotools修改shapefile 属性名乱码问题的更多相关文章

  1. JDK动态代理+反射实现动态修改注解属性值

    这是最近朋友的一个需求,正好闲来无聊有些时间,跟着研究一下,如有不正确的地方,欢迎大家指正~ 一.准备自定义注解 注:如何实现自定义注解,请移步百度. 二.实现 1.实现方式1:通过反射+动态代理动态 ...

  2. Hive分区表新增字段及修改表名,列名,列注释,表注释,增加列,调整列顺序,属性名等操作

    一.Hive分区表新增字段 参考博客:https://blog.csdn.net/yeweiouyang/article/details/44851459 二.Hive修改表名,列名,列注释,表注释, ...

  3. javascript动态修改对象的属性名

    在做东钿业务系统的时候,经常碰到写很多重复的ajax对接,于是就想封装一个方法,但是接收data的字段名不一样,所以就需要用到动态对象属性名这个写法了.其实很简单.直接看一下代码吧.

  4. JS遍历对象修改属性名

    根据接口返回数据中number属性值,对数据进行截取,并改变属性名.直接上码: 下面是需要处理的数据 let data={"minValue":7400, "maxVal ...

  5. 使用DOM解析XML文件,、读取xml文件、保存xml、增加节点、修改节点属性、删除节点

    使用的xml文件 <?xml version="1.0" encoding="GB2312" ?> <PhoneInfo> <Br ...

  6. GDAL C#中文路径,中文属性名称乱码问题

    昨天写的博客,将C#读取shp中文属性值乱码的问题应该可以解决,博客地址为:http://blog.csdn.net/liminlu0314/article/details/54096119,然后又测 ...

  7. C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)

    既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞 ...

  8. [Effective JavaScript 笔记]第39条:不要重用父类的属性名

    假设想给上节讲的场景图库添加收集诊断信息的功能.这对于调试和性能分析很有用. 38条示例续 给每个Actor实例一个唯一的标识数. 添加标识数 function Actor(scene,x,y){ t ...

  9. ibernate学习笔记5---实体类或属性名与数据库关键字冲突、hql命名参数、hql实现通用分页

    一.实体类或属性名与数据库关键字冲突问题1.实体类名与数据库中的关键字冲突比如:实体表User与oracle中的系统表冲突解决方式1:在xml中添加table属性,指定表名,使其不与name默认相等 ...

随机推荐

  1. Android页面事件挂接模拟

    Java没有C#的引用类型.因此事件的挂接一般都是利用接口来实现,有两种方式: 1)定义一个实现事件接口的类,然后实现接口方法,然后通过将这个类的实例加入到事件监听器里面: public class ...

  2. Android活动状态和生存期

    活动状态 1.运行状态(顶层的活动) 2.暂停状态(非顶层的,可见的活动) 3.停止状态(非顶层的,不可见的活动) 4.销毁状态(保证手机的内存充足) 活动的生存期 完整的生存期 onCreate活动 ...

  3. HDU 5438 Ponds dfs模拟

    2015 ACM/ICPC Asia Regional Changchun Online 题意:n个池塘,删掉度数小于2的池塘,输出池塘数为奇数的连通块的池塘容量之和. 思路:两个dfs模拟就行了 # ...

  4. mvc下是如何传值的

    最近在开发一个项目,用的是mvc框架,现将mvc会用到的常用传值方法总结如下: 在讲传递参数方法之前,先简单介绍一下MVC路由及运行机制.     首先,Web 浏览器向服务器发送一条URL 请求,如 ...

  5. 最长回文子串 hihocode 1032 hdu 3068

    最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  6. DedeCMS版权信息SQL命令删除

    dedecms织梦系统底部会自动带有官方链接power by dedecms字样,很多新用户想去除官方的链接,底部调用标签为{dede:global.cfg_poweby/},方法很多,但不鼓励大家删 ...

  7. 【Linux系统引导过程】

    *** 第一步 开机自检 根据主板BIOS中的启动顺序,移交系统控制权. 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它. 这是因为BIO ...

  8. 页面打开pdf格式文件的方法

    <embed width=500 height=300 fullscreen=yes src="1.pdf" />

  9. 洛谷 P3130 [USACO15DEC]计数haybalesCounting Haybales

    P3130 [USACO15DEC]计数haybalesCounting Haybales 题目描述 Farmer John is trying to hire contractors to help ...

  10. 从零開始的Android新项目7 - Data Binding入门篇

    Data Binding自从去年的Google I/O公布到至今,也有近一年的时间了.这一年来,从Beta到如今比較完好的版本号.从Android Studio 1.3到如今2.1.2的支持,能够说D ...