困扰了好几天,一直在尝试各种方法解决Geotools读取shp格式对中文编码的问题。可是昨天一个无意的举动居然让我发觉自己做了太多的无用之功。仔细的看了JavaDoc以及shapefile源代码之后,可以可以明显的看到ShapefileDataStore的构造函数已经发生了很大的变化:
public static final Charset DEFAULT_STRING_CHARSET = Charset.forName("ISO-8859-1"); 这个是ShapefileDataStore对象中定义的字符编码。也正是由于其使用ISO-8859-1编码作为默认编码,所以一直以来,解决geotools抑或geoserver的中文问题总是连绵不绝。
来看看我在2.4中看到的ShapefileDataStore的新的构造函数(当然,贝塔和我聊天说过好像2.3也是作出了同样修改的,可惜我没下2.3的源码,呵呵,但是2.2以前的版本这一块貌似是不同的。权当其是2.4中的“新增”之处吧)
1
public ShapefileDataStore(URL url, boolean useMemoryMappedBuffer)
2
throws MalformedURLException
3
{
4
this(url, useMemoryMappedBuffer, DEFAULT_STRING_CHARSET);
5
}
6
7
public ShapefileDataStore(URL url, boolean useMemoryMappedBuffer, Charset dbfCharset)
8
throws MalformedURLException
9
{
10
readWriteLock = new Lock();
11
namespace = null;
12
this.useMemoryMappedBuffer = true;
13
String filename = null;
14
shpURL = ShapefileDataStoreFactory.toShpURL(url);
15
dbfURL = ShapefileDataStoreFactory.toDbfURL(url);
16
shxURL = ShapefileDataStoreFactory.toShxURL(url);
17
prjURL = ShapefileDataStoreFactory.toPrjURL(url);
18
xmlURL = ShapefileDataStoreFactory.toXmlURL(url);
19
this.dbfCharset = dbfCharset;
20
} 列下使用Geotools 2.4操作shp格式的代码如下:
代码1:
1
public class ReadShape {
2
public static void main(String[] args)
3
throws FileNotFoundException,MalformedURLException,IOException{
4
5
File shpFile=new File("shp/市区地物_point.dbf");
6
ShapefileDataStore shpDataStore=new ShapefileDataStore(shpFile.toURL());
7
shpDataStore.setStringCharset(Charset.forName("GBK"));
8
FeatureSource fs=shpDataStore.getFeatureSource();
9
FeatureCollection collection = fs.getFeatures();
10
FeatureIterator iterator = collection.features();
11
int numOfAttr=0;
12
try {
13
while( iterator.hasNext() ){
14
Feature feature = iterator.next();
15
numOfAttr = feature.getNumberOfAttributes();
16
for(int i=0;i<numOfAttr;i++){
17
String temp=feature.getAttribute(i).toString();
18
System.out.print(temp+"\t");
19
}
20
21
System.out.println();
22
}
23
}
24
finally {
25
iterator.close();
26
}
27
}
28
} 代码2:
1
public class ReadSHP {
2
public static void main(String[] args)
3
throws FileNotFoundException,MalformedURLException,IOException{
4
5
//初始化FileChannel对象
6
FileChannel in = new FileInputStream("shp/市区地物_point.dbf").getChannel();
7
DbaseFileReader dr=new DbaseFileReader(in, true,Charset.forName("UTF-8"));
8
DbaseFileHeader dh = dr.getHeader();
9
int fields = dh.getNumFields();
10
for(int i=0;i<fields;i++){
11
System.out.print(dh.getFieldName(i)+" ");//打印当前属性名
12
}
13
System.out.print("\n");
14
while(dr.hasNext()){
15
DbaseFileReader.Row row = dr.readRow();
16
for (int i=0;i<fields;i++){
17
Object data = row.read(i);
18
if(dh.getFieldName(i).equals("NAME")){
19
System.out.print(data);
20
}else{
21
System.out.print(data);
22
}
23
System.out.print("\t");
24
}
25
System.out.println();
26
}
27
dr.close();
28
}
29
} 两段代码都可以直接运行。当然,从个人角度来看,代码2是我比较推荐的。不管是效率还是安全性,FileChannel对象比File对象应该还是强一些。
算是又解决了一个问题。
十一期间准备自己写一个shp2svg和shp2sql的小程序。第一呢,geoserver生成的svg样式也好,标注名称也好都好像不太好(也许是我自己对geoserver不熟悉的原因);第二呢,严重怀疑postgis自带的shp2pgsql这个程序对编码的支持度。除非我的数据库编码是EUN_CN,否则导入的数据是肯定有问题。
不在考虑那些让我烦心的事情,也不想做一个“人无远虑,必有近忧”的思想者。一心一意专注于自己的爱好。其他时间也许“身不由己”,但是十一长假还是可以做到的。准备回乡下,到我的那间田间小屋去,断网6天!