• 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)
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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)
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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对象,源码如下:
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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.   
    6.         Shapefile shapefile = new Shapefile(shpFilePath);  
    7.         System.out.println(shapefile.getShapeType());  
    或者:---------------------------------------------------------------------------------------
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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.   
    6.         InputStream shpInputStream = new FileInputStream(shpFilePath);  
    7.         InputStream shxInputStream = new FileInputStream(shxFilePath);  
    8.         InputStream dbfInputStream = new FileInputStream(dbfFilePath);  
    9.         InputStream prjInputStream = new FileInputStream(prjFilePath);  
    10.   
    11.         // 实例化一个shapefile类  
    12.          Shapefile shapefile = new Shapefile(shpInputStream, shxInputStream,  
    13.          dbfInputStream, prjInputStream);  
    14.         System.out.println(shapefile.getShapeType()); // shape类型  
     
    这里需要说明的一点是,一开始的时候我是用的Shapefile(Object source)方法,但是报错:Source is NULL,不知是什么原因;用下面这种方法就可以,这个可以不必太纠结。

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

    在shapefile.java文件中可以找到 attributeFile字段,包含shapefile文件的属性信息,但是其权限是protected,只需在原java文件中添加一个方法返回改字段值即可。改完源码,重新导出jar文件覆盖引用即可。
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. protected DBaseFile             attributeFile;  
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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文件的类型、字段个数以及记录个数。另外输出所有字段名
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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.       
    11.     for (int i = 0; i < fieldCount; i++)  
    12.     {  
    13.         System.out.println(dBaseFields[i].getName());  
    14.     }  
    运行结果如下:
    在ArcMap下打开shp文件的属性表,对比可知输出的结果是正确的。

    3、获取字段值

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. // 解析shape文件  
    2.         try  
    3.         {  
    4.             while (shapefile.hasNext())  
    5.             {  
    6.                 ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录  
    7.                 DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息  
    8.                                                   
    9.                 Object[] values = dBaseRecord.getValues().toArray();//获取字段值集合  
    10.   
    11.                 for (int i = 0; i < values.length; i++)  
    12.                 {  
    13.                     System.out.println(values[i].toString());  
    14.                 }  
    15.                 System.out.println("------------------");  
    16.             }  
    17.         }  
    18.         catch (Exception e)  
    19.         {  
    20.             e.printStackTrace();  
    21.             System.out.println("解析shapefile文件出错!");  
    22.         }  
    23.         finally  
    24.         {  
    25.             WWIO.closeStream(shapefile, shpFilePath);  
    26.             WWIO.closeStream(shapefile, shxFilePath);  
    27.             WWIO.closeStream(shapefile, dbfFilePath);  
    28.             WWIO.closeStream(shapefile, prjFilePath);  
    29.   
    30.         }  
    思路很简单:shapefile文件—>获取一条记录—>获取记录的属性信息-->获取字段值集合。但是有一个问题:不支持中文字段值
    调整后运行结果如下:

    ArcMap下的属性表如下图所示:
    通过对比,发现字段值虽然都读取了,但是顺序却是乱的。目前还未发现是什么原因,下一篇博客再来解决这个问题字段值与字段不对应的问题。下面给出完整的代码:
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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.   
    17.         InputStream shpInputStream = new FileInputStream(shpFilePath);  
    18.         InputStream shxInputStream = new FileInputStream(shxFilePath);  
    19.         InputStream dbfInputStream = new FileInputStream(dbfFilePath);  
    20.         InputStream prjInputStream = new FileInputStream(prjFilePath);  
    21.   
    22.         // 实例化一个shapefile类  
    23.          Shapefile shapefile = new Shapefile(shpInputStream, shxInputStream,  
    24.          dbfInputStream, prjInputStream);  
    25.       
    26.   
    27.         // 获取shp属性表  
    28.         DBaseFile dBaseFile = shapefile.getAttributesTable();  
    29.         int fieldCount = dBaseFile.getNumberOfFields(); // 字段数  
    30.         int recordsCount = dBaseFile.getNumberOfRecords(); // 记录数  
    31.         System.out.println("字段数为:" + fieldCount);  
    32.         System.out.println("记录数为:" + recordsCount);  
    33.         System.out.println(shapefile.getShapeType()); // shape类型  
    34.         //获取字段集合  
    35.         DBaseField [] dBaseFields=dBaseFile.getFields();  
    36.           
    37.         for (int i = 0; i < fieldCount; i++)  
    38.         {  
    39.             System.out.print(dBaseFields[i].getName()+"    ");  
    40.         }  
    41.         System.out.println();  
    42.         // 解析shape文件  
    43.         try  
    44.         {  
    45.             while (shapefile.hasNext())  
    46.             {  
    47.                 ShapefileRecord record = shapefile.nextRecord(); // 获取一条记录  
    48.                 DBaseRecord dBaseRecord = record.getAttributes(); // 获取该记录的属性信息  
    49.                                                   
    50.                 Object[] values = dBaseRecord.getValues().toArray();//获取字段值集合  
    51.   
    52.                 for (int i = 0; i < values.length; i++)  
    53.                 {  
    54.                     System.out.print(values[i].toString()+"        ");  
    55.                 }  
    56.                 System.out.println("------------------");  
    57.             }  
    58.         }  
    59.         catch (Exception e)  
    60.         {  
    61.             e.printStackTrace();  
    62.             System.out.println("解析shapefile文件出错!");  
    63.         }  
    64.         finally  
    65.         {  
    66.             WWIO.closeStream(shapefile, shpFilePath);  
    67.             WWIO.closeStream(shapefile, shxFilePath);  
    68.             WWIO.closeStream(shapefile, dbfFilePath);  
    69.             WWIO.closeStream(shapefile, prjFilePath);  
    70.   
    71.         }  
    72.   
    73.     }  

    -----------------------------------------------华丽的分割线----------------------------------------------
    关于上面提到的获取的字段与字段值不对应的问题解决办法:根据字段名来获取字段值。
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    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.                 }  
    17.   
    18.                 System.out.println("------------------");  
    19.             }  
    执行结果如下图所示。
    您好, shp 文件,属性值中文乱码问题,我是这么解决的
    修改 gov.nasa.worldwind.formats.shapefile.DBaseFile;下的
    decodeString 方法中的UTF-8 类型改为 GBK类型,希望对您有用
  • 相关阅读:
    Tomcat下使用war包发布项目
    shell编程报错:“syntax error near unexpected token `”
    undo表空间不足,ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS2'
    HTML快速入门
    HTTP协议快速入门
    Java Web应用的开发模式
    使用Jekyll搭建免费的Github Pages个人博客
    前端模拟API数据的两种方式
    Node.js学习笔记
    socket.io笔记
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6774592.html
Copyright © 2020-2023  润新知