geotools修改shapefile 属性名乱码问题

在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);
            }
        }

时间: 2024-11-10 16:20:02

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

geotools读写shapefile及ArcMap打开shapefile乱码解决

geotools读写shapefile主要依赖于两个类,FeatureReader和FeatureWriter,具体使用可参考geotools相关文档. ArcMap 默认只读取gbk编码的shapefile,要读取UTF-8编码的shapefile,需要在shapefile同级目录下增加.cpg文件,编辑内容为UTF-8即可. 参考自以下资料 http://gis.stackexchange.com/questions/137753/how-to-change-encoding-options

JS遍历对象修改属性名

根据接口返回数据中number属性值,对数据进行截取,并改变属性名.直接上码: 下面是需要处理的数据 let data={"minValue":7400, "maxValue":"18500", "value":{ "value":[ {"dmdDate":"2019-05","dmdAppValue":"9999"}, {&q

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

一.实体类或属性名与数据库关键字冲突问题1.实体类名与数据库中的关键字冲突比如:实体表User与oracle中的系统表冲突解决方式1:在xml中添加table属性,指定表名,使其不与name默认相等 [html] view plaincopyprint? <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hiber

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

既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞定,让PropertyGrid显示Control的所有属性.可是这里显示的属性名是英文的.对于我们开发人员来说这无可厚非,我们也乐于接受.并且让PropertyGrid显示中文属性名,这对于我们开发人员的使用来说显得多此一举.可是,对于我这种类型的一个应用工具,英文属性名对于很多客户来说可能就很难懂

用JavaScript修改CSS属性的代码

用JavaScript修改CSS属性的代码 作者: 字体:[增加 减小] 类型:转载 时间:2013-05-06我要评论 这篇文章主要介绍用原生的javascript修改CSS属性的方法,需要的朋友可以参考下 用JavaScript修改CSS属性 只有写原生的javascript了. 1.用JS修改标签的 class 属性值: class 属性是在标签上引用样式表的方法之一,它的值是一个样式表的选择符,如果改变了 class 属性的值,标签所引用的样式表也就更换了,所以这属于第一种修改方法. 更

获取强类型检测的属性名

在使用EF的Codefirst时,由于EF的局限性,不得不让我们去拼一些查询语句,如下: string sql = string.Format("select ID,[Name] from User"):... 但是这样的代码是没有类型检测的,比如某天项目经理强迫症犯了,将User实体类的“ID”改成”UserID“,那么程序就会报查询异常错误.那怎么做到强类型检测呢? 方法一(推荐): using System.Linq.Expressions;   /***************

在xcode5中修改整个项目名

总会遇到几个项目,在做到一半的时候被要求改项目名,网上找了下相关的资料,大多数是xcode5以前的版本,所以解决好了在这里mark一下,给需要的人. 目标为:将项目名XCD4改成xcd5. 先上结果图:==> 1.在左侧的导航区域点击两次项目名,两次间隔时间稍微长些,项目名会变成可编辑状态. 将名称修改为xcd5后按enter键弹出一个对话框,这个时候放心的点击Rename就好了,在随后弹出的对话框中点击Enable.OK,第一步完成. 2.点击product==>Scheme==>Ma

Windows 修改电脑属性(一)

修改电脑属性里的注册信息 修改电脑属性的注册信息 运行注册表的方法:开始→运行→regedit→确定 1.CPU型号可以注册表编辑器中定位到下面的位置: HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0,然后找到名为ProcessorNameString的键值,将其中的值改为自己喜欢的就可以 2.显卡型号 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\V

深入了解JavaBean规范中的属性名和setter/getter方法

JavaBean规范文档:http://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/ 关于属性名的部分: Utility method to take a string and convert it to normal Java variable name capitalization. This normally means converting the first character from u