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)

  1. /**
  2. * Opens a Shapefile from an InputStream, and InputStreams to its optional
  3. * resources.
  4. * <p/>
  5. * The source Shapefile may be accompanied optional streams to an index
  6. * resource stream, an attribute resource stream, and a projection resource
  7. * stream. If any of these streams are null or cannot be read for any
  8. * reason, the Shapefile opens without that information.
  9. * <p/>
  10. * This throws an exception if the shapefile's coordinate system is
  11. * unsupported.
  12. *
  13. * @param shpStream
  14. *            the shapefile geometry file stream.
  15. * @param shxStream
  16. *            the index file stream, can be null.
  17. * @param dbfStream
  18. *            the attribute file stream, can be null.
  19. * @param prjStream
  20. *            the projection file stream, can be null.
  21. * @throws IllegalArgumentException
  22. *             if the shapefile geometry stream <code>shpStream</code> is
  23. *             null.
  24. * @throws WWRuntimeException
  25. *             if the shapefile cannot be opened for any reason, or if the
  26. *             shapefile's coordinate system is unsupported.
  27. */
  28. public Shapefile(InputStream shpStream, InputStream shxStream,
  29. InputStream dbfStream, InputStream prjStream)
  30. {
  31. this(shpStream, shxStream, dbfStream, prjStream, null);
  32. }

输入文件流分别对应着.shp .shx .dbf .prj文件

(2)
  1. /**
  2. * Opens an Shapefile from a general source. The source type may be one of
  3. * the following:
  4. * <ul>
  5. * <li>{@link java.io.InputStream}</li>
  6. * <li>{@link java.net.URL}</li>
  7. * <li>{@link File}</li>
  8. * <li>{@link String} containing a valid URL description or a file or
  9. * resource name available on the classpath.</li>
  10. * </ul>
  11. * <p/>
  12. * The source Shapefile may be accompanied by an optional index file,
  13. * attribute file, and projection file. To be recognized by this Shapefile,
  14. * accompanying files must be in the same logical folder as the Shapefile,
  15. * have the same filename as the Shapefile, and have suffixes ".shx",
  16. * ".dbf", and ".prj" respectively. If any of these files do not exist, or
  17. * cannot be read for any reason, the Shapefile opens without that
  18. * information.
  19. * <p/>
  20. * This throws an exception if the shapefile's coordinate system is
  21. * unsupported, or if the shapefile's coordinate system is unsupported.
  22. *
  23. * @param source
  24. *            the source of the shapefile.
  25. * @throws IllegalArgumentException
  26. *             if the source is null or an empty string.
  27. * @throws WWRuntimeException
  28. *             if the shapefile cannot be opened for any reason.
  29. */
  30. public Shapefile(Object source)
  31. {
  32. this(source, null);
  33. }

这种方法秩序给出shp文件的路径即可,但是若只有shp文件,缺少shx等文件则无法解析shape文件。

根据以上两种方法来实例化一个shapefile对象,源码如下:
  1. String shpFilePath = "D:\\Users\\wwj_data\\states.shp";
  2. String shxFilePath = "D:\\Users\\wwj_data\\states.shx";
  3. String dbfFilePath = "D:\\Users\\wwj_data\\states.dbf";
  4. String prjFilePath = "D:\\Users\\wwj_data\\states.prj";
  5. Shapefile shapefile = new Shapefile(shpFilePath);
  6. System.out.println(shapefile.getShapeType());

或者:---------------------------------------------------------------------------------------

  1. String shpFilePath = "D:\\Users\\wwj_data\\states.shp";
  2. String shxFilePath = "D:\\Users\\wwj_data\\states.shx";
  3. String dbfFilePath = "D:\\Users\\wwj_data\\states.dbf";
  4. String prjFilePath = "D:\\Users\\wwj_data\\states.prj";
  5. InputStream shpInputStream = new FileInputStream(shpFilePath);
  6. InputStream shxInputStream = new FileInputStream(shxFilePath);
  7. InputStream dbfInputStream = new FileInputStream(dbfFilePath);
  8. InputStream prjInputStream = new FileInputStream(prjFilePath);
  9. // 实例化一个shapefile类
  10. Shapefile shapefile = new Shapefile(shpInputStream, shxInputStream,
  11. dbfInputStream, prjInputStream);
  12. System.out.println(shapefile.getShapeType()); // shape类型
 
这里需要说明的一点是,一开始的时候我是用的Shapefile(Object source)方法,但是报错:Source is NULL,不知是什么原因;用下面这种方法就可以,这个可以不必太纠结。

2、获取shapefile文件的属性表信息

在shapefile.java文件中可以找到 attributeFile字段,包含shapefile文件的属性信息,但是其权限是protected,只需在原java文件中添加一个方法返回改字段值即可。改完源码,重新导出jar文件覆盖引用即可。
  1. protected DBaseFile             attributeFile;
  1. /**
  2. *
  3. * @方法名称: getAttributesTable ;
  4. * @方法描述:  获取属性表 ;
  5. * @参数 :@return
  6. * @返回类型: DBaseFile ;
  7. * @创建人:奔跑的鸡丝 ;
  8. * @创建时间:2014-12-1 下午12:55:33;
  9. * @throws
  10. */
  11. public DBaseFile getAttributesTable()
  12. {
  13. return this.attributeFile;
  14. }

获取属性表后,首先要获取属性表的基本信息,如:shape文件的类型、字段个数以及记录个数。另外输出所有字段名

  1. // 获取shp属性表
  2. DBaseFile dBaseFile = shapefile.getAttributesTable();
  3. int fieldCount = dBaseFile.getNumberOfFields(); // 字段数
  4. int recordsCount = dBaseFile.getNumberOfRecords(); // 记录数
  5. System.out.println("字段数为:" + fieldCount);
  6. System.out.println("记录数为:" + recordsCount);
  7. System.out.println(shapefile.getShapeType()); // shape类型
  8. //获取字段集合
  9. DBaseField [] dBaseFields=dBaseFile.getFields();
  10. for (int i = 0; i < fieldCount; i++)
  11. {
  12. System.out.println(dBaseFields[i].getName());
  13. }

运行结果如下:

在ArcMap下打开shp文件的属性表,对比可知输出的结果是正确的。

3、获取字段值

  1. // 解析shape文件
  2. try
  3. {
  4. while (shapefile.hasNext())
  5. {
  6. ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录
  7. DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息
  8. Object[] values = dBaseRecord.getValues().toArray();//获取字段值集合
  9. for (int i = 0; i < values.length; i++)
  10. {
  11. System.out.println(values[i].toString());
  12. }
  13. System.out.println("------------------");
  14. }
  15. }
  16. catch (Exception e)
  17. {
  18. e.printStackTrace();
  19. System.out.println("解析shapefile文件出错!");
  20. }
  21. finally
  22. {
  23. WWIO.closeStream(shapefile, shpFilePath);
  24. WWIO.closeStream(shapefile, shxFilePath);
  25. WWIO.closeStream(shapefile, dbfFilePath);
  26. WWIO.closeStream(shapefile, prjFilePath);
  27. }

思路很简单:shapefile文件—>获取一条记录—>获取记录的属性信息-->获取字段值集合。但是有一个问题:不支持中文字段值

调整后运行结果如下:
ArcMap下的属性表如下图所示:
通过对比,发现字段值虽然都读取了,但是顺序却是乱的。目前还未发现是什么原因,下一篇博客再来解决这个问题字段值与字段不对应的问题。下面给出完整的代码:
  1. /**
  2. * @方法名称: shapeFileReader ;
  3. * @方法描述: 读取sh文件 ;
  4. * @参数 :@throws FileNotFoundException
  5. * @返回类型: void ;
  6. * @创建人:奔跑的鸡丝 ;
  7. * @创建时间:2014-12-1 下午12:50:11;
  8. * @throws
  9. */
  10. private void shapeFileReader() throws FileNotFoundException
  11. {
  12. String shpFilePath = "D:\\Users\\wwj_data\\states.shp";
  13. String shxFilePath = "D:\\Users\\wwj_data\\states.shx";
  14. String dbfFilePath = "D:\\Users\\wwj_data\\states.dbf";
  15. String prjFilePath = "D:\\Users\\wwj_data\\states.prj";
  16. InputStream shpInputStream = new FileInputStream(shpFilePath);
  17. InputStream shxInputStream = new FileInputStream(shxFilePath);
  18. InputStream dbfInputStream = new FileInputStream(dbfFilePath);
  19. InputStream prjInputStream = new FileInputStream(prjFilePath);
  20. // 实例化一个shapefile类
  21. Shapefile shapefile = new Shapefile(shpInputStream, shxInputStream,
  22. dbfInputStream, prjInputStream);
  23. // 获取shp属性表
  24. DBaseFile dBaseFile = shapefile.getAttributesTable();
  25. int fieldCount = dBaseFile.getNumberOfFields(); // 字段数
  26. int recordsCount = dBaseFile.getNumberOfRecords(); // 记录数
  27. System.out.println("字段数为:" + fieldCount);
  28. System.out.println("记录数为:" + recordsCount);
  29. System.out.println(shapefile.getShapeType()); // shape类型
  30. //获取字段集合
  31. DBaseField [] dBaseFields=dBaseFile.getFields();
  32. for (int i = 0; i < fieldCount; i++)
  33. {
  34. System.out.print(dBaseFields[i].getName()+"    ");
  35. }
  36. System.out.println();
  37. // 解析shape文件
  38. try
  39. {
  40. while (shapefile.hasNext())
  41. {
  42. ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录
  43. DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息
  44. Object[] values = dBaseRecord.getValues().toArray();//获取字段值集合
  45. for (int i = 0; i < values.length; i++)
  46. {
  47. System.out.print(values[i].toString()+"        ");
  48. }
  49. System.out.println("------------------");
  50. }
  51. }
  52. catch (Exception e)
  53. {
  54. e.printStackTrace();
  55. System.out.println("解析shapefile文件出错!");
  56. }
  57. finally
  58. {
  59. WWIO.closeStream(shapefile, shpFilePath);
  60. WWIO.closeStream(shapefile, shxFilePath);
  61. WWIO.closeStream(shapefile, dbfFilePath);
  62. WWIO.closeStream(shapefile, prjFilePath);
  63. }
  64. }

-----------------------------------------------华丽的分割线----------------------------------------------

关于上面提到的获取的字段与字段值不对应的问题解决办法:根据字段名来获取字段值。
  1. while (shapefile.hasNext())
  2. {
  3. ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录
  4. DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息
  5. ArrayList<String> fieldArrayList = new ArrayList<String>();
  6. for (int i = 0; i < fieldCount; i++)
  7. {
  8. /**
  9. * 根据字段名称来获取字段值
  10. */
  11. String fieldValue = dBaseRecord.getValue(
  12. dBaseFields[i].getName()).toString(); //
  13. fieldArrayList.add(fieldValue);
  14. System.out.print(fieldValue + "        ");
  15. }
  16. System.out.println("------------------");
  17. }

执行结果如下图所示。

您好, shp 文件,属性值中文乱码问题,我是这么解决的
修改 gov.nasa.worldwind.formats.shapefile.DBaseFile;下的
decodeString 方法中的UTF-8 类型改为 GBK类型,希望对您有用

World Wind Java开发之六——解析shape文件(转)的更多相关文章

  1. [转]World Wind Java开发之四——搭建本地WMS服务器

    在提供地理信息系统客户端时,NASA还为用户提供了开源的WMS Server 服务器应用:World Wind WMS Server.利用这个应用,我们可以架设自己的WMS服务并使用自己的数据(也支持 ...

  2. java jar包解析:打包文件,引入文件

    java jar包解析:打包文件,引入文件 cmd下: jar命令:package包打包 javac命令:普通类文件打包 Hello.java: package org.lxh.demo; publi ...

  3. World Wind Java开发之一(转)

    http://blog.csdn.net/giser_whu/article/details/40477235 参照<World wind Java三维地理信息系统开发指南随书光盘>以及官 ...

  4. [转]World Wind Java开发之五——读取本地shp文件

    World Wind Java 使用IconLayer图层类表现点和多点数据,使用RenderableLayer图层表现线和面数据,一个图层只能对应一组shape文件.World Wind Java首 ...

  5. World Wind Java开发之五——读取本地shp文件(转)

    http://blog.csdn.net/giser_whu/article/details/41484433 World Wind Java 使用IconLayer图层类表现点和多点数据,使用Ren ...

  6. JAVA使用SAX解析XML文件

    在我的另一篇文章(http://www.cnblogs.com/anivia/p/5849712.html)中,通过一个例子介绍了使用DOM来解析XML文件,那么本篇文章通过相同的XML文件介绍如何使 ...

  7. Java 创建过滤器 解析xml文件

    今天写了一个过滤器demo,现在是解析actions.xml文件,得到action中的业务规则:不需要导入任何jar包 ActionFilter过滤器类: package accp.com.xh.ut ...

  8. java使用dom4j解析xml文件

    关于xml的知识,及作用什么的就不说了,直接解释如何使用dom4j解析.假如有如下xml: dom4j解析xml其实很简单,只要你有点java基础,知道xml文件.结合下面的xml文件和java代码, ...

  9. Java:JXL解析Excel文件

    项目中,有需求要使用JXL解析Excel文件. 解析Excel文件 我们先要将文件转化为数据流inputStream. 当inputStream很大的时候 会造成Java虚拟器内存不够 抛出内存溢出 ...

随机推荐

  1. 前端编码规范 -- html篇

    文档类型 推荐使用 HTML5 的文档类型申明: <!DOCTYPE html> (建议使用 text/html 格式的 HTML.避免使用 XHTML.XHTML 以及它的属性,比如 a ...

  2. loj#6433. 「PKUSC2018」最大前缀和(状压dp)

    传送门 今天\(PKUWC\)试机的题 看着边上的大佬们一个个\(A\)穿咱还是不会-- 我们考虑枚举最大前缀和,如果一个前缀\(1\)到\(p\)是最大前缀和,那么\(p\)后面的所有前缀和都要小于 ...

  3. 关于写PPT

    如果你要给别人讲东西,要记得你的受众的不同,你的讲法也应该有不同,侧重点应该有所区别. 如果作为一个老师,你的PPT应该是让人看懂,把人讲懂,这是你的最终目的所在.如果你是一个毕业生,你要围绕你要解决 ...

  4. POST和 GET

    http GET 和 POST 请求的优缺点.区别以及误区     Get和Post在面试中一般都会问到,一般的区别: (1)post更安全(不会作为url的一部分,不会被缓存.保存在服务器日志.以及 ...

  5. 设计模式——抽象工厂(Abstract Factory)

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类. ——DP UML类图 模式说明 抽象工厂与工厂方法在定义上最明显的区别是“创建一系列相关或相互依赖对象的接口”,由此可以看出抽象工 ...

  6. MySQL存储过程的动态行转列

    MySQL存储过程中使用动态行转列 最近做项目关于数据报表处理,然而数据库存储格式和报表展现形式不同,需要进行一下行转列的操作,在做上一个项目的时候也看了一下,但是后来换了读取方式,也就没深入研究这个 ...

  7. linux下WPS的使用

    WPS退出了wps for linux ,高版本的一直安装不上,低版本的原来在桌面都有图标,重装后安装位置不是很明显打开关闭不是很方便.并且也不利于在终端模式下使用.现简单总结一下wps的表格 文字 ...

  8. Java集合——集合框架Iterator接口

    1.集合输出 很多情况下我们需要把集合的内容进行输出,也就是遍历集合. 遍历集合的方式有以下几种: 1.Iterator 2.ListIterator 3.Enumeration(枚举方式,比较老一般 ...

  9. RN 从上手到“放弃”

    RN 从上手到"放弃" 前言: react-native,相对于最近

  10. Zookeeper问题汇总

    1. 遗留问题 a). zookeeper集群如何保证请求的均匀分布? 2. ZK概念澄清 2.1 ZK节点类型 CreateMode.PERSISTENT //持久节点,该节点客户端断开后不会删除 ...