博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
geotools修改shapefile 属性名乱码问题 (转载)
阅读量:6376 次
发布时间:2019-06-23

本文共 3430 字,大约阅读时间需要 11 分钟。

在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
fids = new HashSet
(); 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(); //此处应改为byte[] bytes = str.getBytes(“GBK”);否则中文还是无法识别 
            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);
            }
        }

 

 

转载自:

你可能感兴趣的文章
函数的递归
查看>>
JavaScript之将JS代码放在什么位置最合适
查看>>
【“零起点”--百度地图手机SDK】如何使用离线地图?
查看>>
深拷贝与浅拷贝复习
查看>>
各种参数的响应时间
查看>>
SQL Server 索引重建脚本
查看>>
23:LVS客户端配置脚本案例
查看>>
Android播放本地视频
查看>>
Hadoop环境搭建
查看>>
Ubuntu和win双系统删除ubuntu开机出错
查看>>
uva 753(最大流)
查看>>
python 匹配中文和英文
查看>>
vbox下Oracle Enterprise liunx5.4虚拟机安装10G RAC实验(三)
查看>>
页面注册类
查看>>
webstorm快捷键
查看>>
uploadify 上传 大文件没有反映
查看>>
poj1250 Tanning Salon
查看>>
SaaS
查看>>
hdu1535(最短路)
查看>>
poj3974(manacher)
查看>>