World Wind Java开发之六——解析shape文件(转)
http://blog.csdn.net/giser_whu/article/details/41647117
最近一直忙于导师项目的事情了,几天没更新了,昨天和今天研究了下WWJ解析shp文件的源代码,现在记录下,希望可以帮到更多的人!
上一篇博客:World Wind Java开发之五——读取本地shp文件只讲了如何加载shp文件,没有涉及到shp文件的解析,我们这篇博客紧接上一篇博客,利用WWJ来解析shp文件。首先来看用到的源码包和相关类,如下图所示。解析shp文件主要用到Shapefile(shapefile文件类)、ShapefileRecord(shape文件记录类)、DBaseRecord类以及DBaseField(字段类)
1、读取shapefile文件
由上图可以看出有要实例化一个shapefile对象有六种方法,以其中的两种为例,看下源码:
(1)
输入文件流分别对应着.shp .shx .dbf .prj文件
- /**
- * Opens a Shapefile from an InputStream, and InputStreams to its optional
- * resources.
- * <p/>
- * The source Shapefile may be accompanied optional streams to an index
- * resource stream, an attribute resource stream, and a projection resource
- * stream. If any of these streams are null or cannot be read for any
- * reason, the Shapefile opens without that information.
- * <p/>
- * This throws an exception if the shapefile's coordinate system is
- * unsupported.
- *
- * @param shpStream
- * the shapefile geometry file stream.
- * @param shxStream
- * the index file stream, can be null.
- * @param dbfStream
- * the attribute file stream, can be null.
- * @param prjStream
- * the projection file stream, can be null.
- * @throws IllegalArgumentException
- * if the shapefile geometry stream <code>shpStream</code> is
- * null.
- * @throws WWRuntimeException
- * if the shapefile cannot be opened for any reason, or if the
- * shapefile's coordinate system is unsupported.
- */
- public Shapefile(InputStream shpStream, InputStream shxStream,
- InputStream dbfStream, InputStream prjStream)
- {
- this(shpStream, shxStream, dbfStream, prjStream, null);
- }
(2)
- /**
- * Opens an Shapefile from a general source. The source type may be one of
- * the following:
- * <ul>
- * <li>{@link java.io.InputStream}</li>
- * <li>{@link java.net.URL}</li>
- * <li>{@link File}</li>
- * <li>{@link String} containing a valid URL description or a file or
- * resource name available on the classpath.</li>
- * </ul>
- * <p/>
- * The source Shapefile may be accompanied by an optional index file,
- * attribute file, and projection file. To be recognized by this Shapefile,
- * accompanying files must be in the same logical folder as the Shapefile,
- * have the same filename as the Shapefile, and have suffixes ".shx",
- * ".dbf", and ".prj" respectively. If any of these files do not exist, or
- * cannot be read for any reason, the Shapefile opens without that
- * information.
- * <p/>
- * This throws an exception if the shapefile's coordinate system is
- * unsupported, or if the shapefile's coordinate system is unsupported.
- *
- * @param source
- * the source of the shapefile.
- * @throws IllegalArgumentException
- * if the source is null or an empty string.
- * @throws WWRuntimeException
- * if the shapefile cannot be opened for any reason.
- */
- public Shapefile(Object source)
- {
- this(source, null);
- }
根据以上两种方法来实例化一个shapefile对象,源码如下:
- String shpFilePath = "D:\\Users\\wwj_data\\states.shp";
- String shxFilePath = "D:\\Users\\wwj_data\\states.shx";
- String dbfFilePath = "D:\\Users\\wwj_data\\states.dbf";
- String prjFilePath = "D:\\Users\\wwj_data\\states.prj";
- Shapefile shapefile = new Shapefile(shpFilePath);
- System.out.println(shapefile.getShapeType());
- String shpFilePath = "D:\\Users\\wwj_data\\states.shp";
- String shxFilePath = "D:\\Users\\wwj_data\\states.shx";
- String dbfFilePath = "D:\\Users\\wwj_data\\states.dbf";
- String prjFilePath = "D:\\Users\\wwj_data\\states.prj";
- InputStream shpInputStream = new FileInputStream(shpFilePath);
- InputStream shxInputStream = new FileInputStream(shxFilePath);
- InputStream dbfInputStream = new FileInputStream(dbfFilePath);
- InputStream prjInputStream = new FileInputStream(prjFilePath);
- // 实例化一个shapefile类
- Shapefile shapefile = new Shapefile(shpInputStream, shxInputStream,
- dbfInputStream, prjInputStream);
- System.out.println(shapefile.getShapeType()); // shape类型
这里需要说明的一点是,一开始的时候我是用的Shapefile(Object source)方法,但是报错:Source is NULL,不知是什么原因;用下面这种方法就可以,这个可以不必太纠结。
2、获取shapefile文件的属性表信息
在shapefile.java文件中可以找到 attributeFile字段,包含shapefile文件的属性信息,但是其权限是protected,只需在原java文件中添加一个方法返回改字段值即可。改完源码,重新导出jar文件覆盖引用即可。
- protected DBaseFile attributeFile;
- /**
- *
- * @方法名称: getAttributesTable ;
- * @方法描述: 获取属性表 ;
- * @参数 :@return
- * @返回类型: DBaseFile ;
- * @创建人:奔跑的鸡丝 ;
- * @创建时间:2014-12-1 下午12:55:33;
- * @throws
- */
- public DBaseFile getAttributesTable()
- {
- return this.attributeFile;
- }
- // 获取shp属性表
- DBaseFile dBaseFile = shapefile.getAttributesTable();
- int fieldCount = dBaseFile.getNumberOfFields(); // 字段数
- int recordsCount = dBaseFile.getNumberOfRecords(); // 记录数
- System.out.println("字段数为:" + fieldCount);
- System.out.println("记录数为:" + recordsCount);
- System.out.println(shapefile.getShapeType()); // shape类型
- //获取字段集合
- DBaseField [] dBaseFields=dBaseFile.getFields();
- for (int i = 0; i < fieldCount; i++)
- {
- System.out.println(dBaseFields[i].getName());
- }
在ArcMap下打开shp文件的属性表,对比可知输出的结果是正确的。
3、获取字段值
- // 解析shape文件
- try
- {
- while (shapefile.hasNext())
- {
- ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录
- DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息
- Object[] values = dBaseRecord.getValues().toArray();//获取字段值集合
- for (int i = 0; i < values.length; i++)
- {
- System.out.println(values[i].toString());
- }
- System.out.println("------------------");
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- System.out.println("解析shapefile文件出错!");
- }
- finally
- {
- WWIO.closeStream(shapefile, shpFilePath);
- WWIO.closeStream(shapefile, shxFilePath);
- WWIO.closeStream(shapefile, dbfFilePath);
- WWIO.closeStream(shapefile, prjFilePath);
- }
调整后运行结果如下:
ArcMap下的属性表如下图所示:
通过对比,发现字段值虽然都读取了,但是顺序却是乱的。目前还未发现是什么原因,下一篇博客再来解决这个问题字段值与字段不对应的问题。下面给出完整的代码:
- /**
- * @方法名称: shapeFileReader ;
- * @方法描述: 读取sh文件 ;
- * @参数 :@throws FileNotFoundException
- * @返回类型: void ;
- * @创建人:奔跑的鸡丝 ;
- * @创建时间:2014-12-1 下午12:50:11;
- * @throws
- */
- private void shapeFileReader() throws FileNotFoundException
- {
- String shpFilePath = "D:\\Users\\wwj_data\\states.shp";
- String shxFilePath = "D:\\Users\\wwj_data\\states.shx";
- String dbfFilePath = "D:\\Users\\wwj_data\\states.dbf";
- String prjFilePath = "D:\\Users\\wwj_data\\states.prj";
- InputStream shpInputStream = new FileInputStream(shpFilePath);
- InputStream shxInputStream = new FileInputStream(shxFilePath);
- InputStream dbfInputStream = new FileInputStream(dbfFilePath);
- InputStream prjInputStream = new FileInputStream(prjFilePath);
- // 实例化一个shapefile类
- Shapefile shapefile = new Shapefile(shpInputStream, shxInputStream,
- dbfInputStream, prjInputStream);
- // 获取shp属性表
- DBaseFile dBaseFile = shapefile.getAttributesTable();
- int fieldCount = dBaseFile.getNumberOfFields(); // 字段数
- int recordsCount = dBaseFile.getNumberOfRecords(); // 记录数
- System.out.println("字段数为:" + fieldCount);
- System.out.println("记录数为:" + recordsCount);
- System.out.println(shapefile.getShapeType()); // shape类型
- //获取字段集合
- DBaseField [] dBaseFields=dBaseFile.getFields();
- for (int i = 0; i < fieldCount; i++)
- {
- System.out.print(dBaseFields[i].getName()+" ");
- }
- System.out.println();
- // 解析shape文件
- try
- {
- while (shapefile.hasNext())
- {
- ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录
- DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息
- Object[] values = dBaseRecord.getValues().toArray();//获取字段值集合
- for (int i = 0; i < values.length; i++)
- {
- System.out.print(values[i].toString()+" ");
- }
- System.out.println("------------------");
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- System.out.println("解析shapefile文件出错!");
- }
- finally
- {
- WWIO.closeStream(shapefile, shpFilePath);
- WWIO.closeStream(shapefile, shxFilePath);
- WWIO.closeStream(shapefile, dbfFilePath);
- WWIO.closeStream(shapefile, prjFilePath);
- }
- }
-----------------------------------------------华丽的分割线----------------------------------------------
关于上面提到的获取的字段与字段值不对应的问题解决办法:根据字段名来获取字段值。
- while (shapefile.hasNext())
- {
- ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录
- DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息
- ArrayList<String> fieldArrayList = new ArrayList<String>();
- for (int i = 0; i < fieldCount; i++)
- {
- /**
- * 根据字段名称来获取字段值
- */
- String fieldValue = dBaseRecord.getValue(
- dBaseFields[i].getName()).toString(); //
- fieldArrayList.add(fieldValue);
- System.out.print(fieldValue + " ");
- }
- System.out.println("------------------");
- }
您好, shp 文件,属性值中文乱码问题,我是这么解决的
修改 gov.nasa.worldwind.formats.shapefile.DBaseFile;下的
decodeString 方法中的UTF-8 类型改为 GBK类型,希望对您有用
修改 gov.nasa.worldwind.formats.shapefile.DBaseFile;下的
decodeString 方法中的UTF-8 类型改为 GBK类型,希望对您有用