婴儿衣服做的网站好,wordpress修改标题,高密做网站的公司,建站时网站地图怎么做目录 前言
一、Shapefile的属性列表信息
1、属性表格信息
2、属性表格包含的要素
二、GeoTools对属性表格的解析
1、常规解析方法
2、基于dbf文件的属性信息读取
三、总结 前言 ESRI Shapefile#xff08;shp#xff09;#xff0c;或简称shapefile#xff0c;是美…
目录 前言
一、Shapefile的属性列表信息
1、属性表格信息
2、属性表格包含的要素
二、GeoTools对属性表格的解析
1、常规解析方法
2、基于dbf文件的属性信息读取
三、总结 前言 ESRI Shapefileshp或简称shapefile是美国环境系统研究所公司ESRI开发的一种空间数据开放格式。该文件格式已经成为了地理信息软件界的一个开放标准这表明ESRI公司在全球的地理信息系统市场的重要性。Shapefile也是一种重要的交换格式它能够在ESRI与其他公司的产品之间进行数据互操作。Shapefile文件用于描述几何体对象点折线与多边形。例如Shapefile文件可以存储井、河流、湖泊等空间对象的几何位置。除了几何位置shp文件也可以存储这些空间对象的属性例如一条河流的名字一个城市的温度等等。 Shapefile属于一种矢量图形格式它能够保存几何图形的位置及相关属性。但这种格式没法存储地理数据的拓扑信息。Shapefile在九十年代初的ArcView GIS的第二个版本被首次应用。许多自由的程序或商业的程序都可以读取Shapefile。Shapefile是一种比较原始的矢量数据存储方式它仅仅能够存储几何体的位置数据而无法在一个文件之中同时存储这些几何体的属性数据。因此Shapefile还必须附带一个二维表用于存储Shapefile中每个几何体的属性信息。Shapefile中许多几何体能够代表复杂的地理事物并为他们提供强大而精确的计算能力。 Shapefile文件指的是一种文件存储的方法实际上该种文件格式是由多个文件组成的。其中要组成一个Shapefile有三个文件是必不可少的它们分别是.shp, .shx与 .dbf文件。表示同一数据的一组文件其文件名前缀应该相同。例如存储一个关于湖的几何与属性数据就必须有lake.shplake.shx与lake.dbf三个文件。而其中“真正”的Shapefile的后缀为shp然而仅有这个文件数据是不完整的必须要把其他两个附带上才能构成一组完整的地理数据。除了这三个必须的文件以外还有八个可选的文件使用它们可以增强空间数据的表达能力。所有的文件名都必须遵循MS DOS的8.3文件名标准文件前缀名8个字符后缀名3个字符如shapefil.shp以方便与一些老的应用程序保持兼容性尽管现在许多新的程序都能够支持长文件名。此外所有的文件都必须位于同一个目录之中。 由于Shapefile有着广泛的适用性是很多公共地理服务所采用的矢量文件规范之一。因此有必要对Shapefile文件进行深度的解析。如果将shapefile类比为一个数据库那么它就是一个database而其中的属性表则是一张一张的物理表。他们两存在天然的对应关系。虽然在前面的博客中我们已经对shapefile的解析有了基本的认识。但是对属性表格的解析并没有介绍得很详细。本文则重点讲解在Java当中如何使用GeoTools来进行属性表格的解析首先在Qgis中重点介绍属性表格的字段信息然后介绍一种常见的属性字段信息解析方式其次介绍基于dbf的属性信息解析方法直接解析dbf文件的方法在很多网络知识中很少见但是却非常有用比如在获取double类型的数值时想获取精度值就可以通过这种方式来获取。学习本文不仅更加熟悉GeoTools对属性表格的解析同时对于如何快速的将Shapefile的属性模型映射成空间库模型有更进一步的认识。希望对您有一定的帮助。
一、Shapefile的属性列表信息 本文主要是讲解如何来深度解析shapefile的属性表因此就有必要对属性列表信息进行一个详细的讲解。
1、属性表格信息 shapefile文件其实是文件数据库的一种它将数据的信息写入到shapefile文件中然后在其它的电脑终端中可以直接共享这些数据解析这些属性信息。为了介绍方便我们将shapefile与常见的关系型数据库进行对比可以这么进行理解。一个shapefile就是一个database而一张表就是一个属性表。属性表格中的字段、数据类型、长度、精度等就是与关系型数据库中的数据列是一个意思而数据行基本就是数据库中一行数据的意思。下面是以某年度某城市POI的矢量数据为例进行讲解在Qgis中打开字段表如下 2、属性表格包含的要素 既然与关系型数据库的数据定义类似那么就有必要对属性表格的每一列的信息进行精准的定义。包括数据类型、数据长度、精度等下面结合示例数据来进行一个深入讲解。
序号参数参数1名称具体的字段名称如name2别名类比于关系数据库的字段别名3类型数据类型比如QString4类型名数据类型名比如StringReal5长度字段的长度比如2556精度double等类型的精度如117注解其它辅助信息 有了上面的信息之后我们也可以根据属性表格来进行空间表的创建这样管理起来也比较方便。在数据库中定义好每一个列的数据信息之后就可以将具体的空间信息填充到每一行中这时候可能就需要外业和内业的工作人员通力配合。 在了解上面的基本信息后在下面的章节中我们就要进行属性表格的深度解析操作。
二、GeoTools对属性表格的解析 本节重点使用两种方法来进行属性表格解析的实战第一种方法是常规的通过featureType的方式来获取属性表格的信息。第二种是基于GeoTools来读取dbf文件来获取元数据信息。这里不仅说明两种方式的优缺点也说明两者的具体开发代码帮助大家来深度掌握GeoTools的属性表解析操作。
1、常规解析方法 首先讲解普通的解析方法同时这种解析的方式在互联网或者很多博客当中是最常见的。也就是直接解析shp文件。具体的解析步骤流程如下所示 这里给出详细的遍历代码如下所示 public void testAttrLength() throws Exception {// 指定Shapefile的文件路径String shpFile C:/BaiduDownload/长沙市2020年POI数据集/长沙市2020年POI数据集/长沙POI数据.shp/风景名胜.shp;FileDataStore dataStore FileDataStoreFinder.getDataStore(new File(shpFile));ShapefileDataStore shapefileDataStore new ShapefileDataStore(new File(shpFile).toURI().toURL());System.out.println(shapefileDataStore.getCharset());// 打开数据存储String[] typeNames dataStore.getTypeNames();System.out.println(typeNames.length);for (String type : typeNames) {System.out.println(type);}// 获取特征类型SimpleFeatureType featureType dataStore.getSchema(dataStore.getTypeNames()[0]);CoordinateReferenceSystem crs featureType.getGeometryDescriptor().getCoordinateReferenceSystem();System.out.println(坐标参考系统: crs);// 获取属性名ListString attributeNames featureType.getAttributeDescriptors().stream().map(attr - attr.getLocalName()).collect(Collectors.toList());System.out.println(Attributes: attributeNames);System.out.println(以下是属性信息的深度解析:----------------------------------------);ListAttributeDescriptor attrDescList featureType.getAttributeDescriptors();System.out.println(attrDescList.size());for (AttributeDescriptor attrDesc : attrDescList) {System.out.println(attrDesc);System.out.println(属性详情:);AttributeType attrType attrDesc.getType();System.out.println(userData attrType.getUserData());System.out.println(数据库数据类型 convertShpFieldType2H2GISOrPG(attrType.getBinding()));System.out.println(attrType);System.out.println(name attrDesc.getName() \tLocalName attrDesc.getLocalName() \t attrDesc.getMaxOccurs() \t attrDesc.getMinOccurs());ListFilter restrictions attrType.getRestrictions();System.out.println(过滤器为 : restrictions);for (Filter filter : restrictions) {if (filter instanceof IsLessThenOrEqualToImpl) {IsLessThenOrEqualToImpl impl (IsLessThenOrEqualToImpl) filter;Expression exp1 impl.getExpression1();Expression exp2 impl.getExpression2();System.out.println(exp1.getClass());System.out.println(exp2.getClass());if (exp1 instanceof LengthFunction exp2 instanceof LiteralExpressionImpl) {LengthFunction length (LengthFunction) exp1;LiteralExpressionImpl literal (LiteralExpressionImpl) exp2;System.out.println( length.getName() :\t literal.getValue());}}}System.out.println(**************************************************);}} 可以看到这里关于数据的属性列表信息尤其是获取字段的长度和精度时是通过在过滤器中的具体子类来实现的。在Filter列表中一定会用到两个表达式对象其中的一个是IsLessThenOrEqualToImpl另一个则是LiteralExpressionImpl通过这两个类来实现长度的控制。因此如果需要在代码中获取具体的长度可以通过这两个表达式对象来获取。同时在进行数据的解析时虽然我们在前面对两者进行了简单的类比但毕竟两者不是一个东西因此在进行数据的存储时具体的设置还是有一定的区分的比如对应的具体数据类型这里我们来提供一个类来进行转换。
/**
* convert shpFileType to db field type
** 备注目前arcgis的字段类型有短整型 长整型 浮点型 双精度 文本 日期
* param value
* return
*/
public static String convertShpFieldType2H2GISOrPG(Class? value) throws Exception {if (value String.class) {//文本return varchar;}if (value Integer.class) {//短整型return int;}if (value Long.class) {//长整型return bigint;}if (value Double.class || value Float.class) {//浮点型 双精度 保留精度比如在金币上运算更安全return numeric;}if (value Date.class) {return TIMESTAMP WITH TIME ZONE ;//日期, 使用包含时区的来处理}if (Geometry.class.isAssignableFrom(value)) {return geometry;}//除了上述真不知道还会有啥了。除非arcgis的shp又增加了新类型那无能为力了抛出异常吧throw new Exception(不支持的类型 value.getName());////if (value.getSuperclass().getName().equals(String.class))// return null;
} 在GeoTools中关于Filter的相关类非常的庞大这里不全部展开以防止抓不住重点。先给一个Filter的类图给朋友们感兴趣的可以先了解一下。 通过以上的步骤和示例代码我们可以在控制台中输出以下信息 为了方便展示字段的解析这里特意将复制一段处理的输出信息
AttributeDescriptorImpl WGS84_纬 Double:Double nillable 0:1
属性详情:
userData{}
数据库数据类型numeric
AttributeTypeImpl DoubleDouble
restrictions[ length([.]) 19 ]
nameWGS84_纬 LocalNameWGS84_纬 1 0
过滤器为 : [[ length([.]) 19 ]]
class org.geotools.filter.LengthFunction
class org.geotools.filter.LiteralExpressionImpl
length: 19 可以看到通过上述的代码就可以获取属性表格的字段名、字段类型、字段的长度等信息有了这些信息我们其实可以做的事情很多了。不知道大家发现一个问题没有在上述的代码中并没有返回精度即11位小数的长度。上述代码是无法实现的。那么有没有什么办法来实现精度值的获取呢。
2、基于dbf文件的属性信息读取 众所周知在shapefile文件夹中除了shp文件之外另外一个prj和dbf文件也是缺一不可的。既然我们无法通过读取shp来实现精度的精确读取那么是否可以从这两个文件当中来获取呢shp文件有我们定义好的空间信息而大量的属性表格我们是存放在dbf中因此我们来测试读取dbf文件看能否找到另外的一条大路。 幸运的是在Geotools当中官方提供了DbaseFileReader这个类通过这个类实现对dbf文件的读取之前也查找了一些相关的资料但是很少有博主写这种实现模式。这里提供基于DbaseFileReader的实现方式代码实现更简单性能更好。其原理非常简单通过DbaseFileReader来获取DbaseFileHeader然后就可以遍历DbaseFileHeader中的信息就可以实现所有信息的识别。代码如下 /*** - 读取dbf文件* throws IOException*/Testpublic void testReadDbf() throws IOException {File dbfFile new File(C:/BaiduDownload/长沙市2020年POI数据集/长沙市2020年POI数据集/长沙POI数据.shp/风景名胜.shp);// 打开 DBF 文件ShpFiles shpFile new ShpFiles(dbfFile);System.out.println(Charset.defaultCharset().toString());DbaseFileReader dbfReader new DbaseFileReader(shpFile, true, Charset.defaultCharset());// 读取 DBF 文件的头信息DbaseFileHeader header dbfReader.getHeader();System.out.println(header.getNumFields());System.out.println(header.getNumRecords());for (int i 0; i header.getNumFields(); i) {System.out.println(header.getFieldName(i) \t header.getFieldLength(i) \t header.getFieldType(i) \t header.getFieldDecimalCount(i));}// 关闭 DBF 文件读取器dbfReader.close();
} 这个类的方法如下
Modifier and TypeMethodDescriptionvoidclose() Clean up all resources associated with this reader.Highly recomended. protected intfill(ByteBuffer buffer, ReadableByteChannel channel)DbaseFileHeadergetHeader() Get the header from this file. booleanhasNext() Query the reader as to whether there is another record. Stringid() An id for the reader. static voidmain(String[] args)voidread() Reads the next record into memory. Object[]readEntry() Get the next record (entry). Object[]readEntry(Object[] entry) Copy the next entry into the array. Object[]readEntry(Object[] entry, int offset) Copy the next record into the array starting at offset. ObjectreadField(int fieldNum) Reads a single field from the current record and returns it. DbaseFileReader.RowreadRow()voidskip() Skip the next record. voidtransferTo(DbaseFileWriter writer) Transfer, by bytes, the next record to the writer. 想要获取属性就是通过获取Head对象即可实现属性列表的深度解析。返回DbaseFileHead它的方法如下表所示
Modifier and TypeMethodDescriptionvoidaddColumn(String inFieldName, char inFieldType, int inFieldLength, int inDecimalCount) Add a column to this DbaseFileHeader. Class?getFieldClass(int i) Determine the most appropriate Java Class for representing the data in the field. intgetFieldDecimalCount(int inIndex) Get the decimal count of this field. intgetFieldLength(int inIndex) Returns the field length in bytes. StringgetFieldName(int inIndex) Get the field name. chargetFieldType(int inIndex) Get the character class of the field. intgetHeaderLength() Get the length of the header intgetLargestFieldSize() Get the largest field size of this table. DategetLastUpdateDate() Get the date this file was last updated. longgetLengthForRecords(int records) Returns the expected file size for the given number of records in the file intgetNumFields() Return the number of fields in the records. intgetNumRecords() Return the number of records in the file intgetRecordLength() Get the length of the records in bytes. voidreadHeader(ByteBuffer in) Read the header data from the DBF file. voidreadHeader(ReadableByteChannel channel) Read the header data from the DBF file. intremoveColumn(String inFieldName) Remove a column from this DbaseFileHeader. voidsetNumRecords(int inNumRecords) Set the number of records in the file StringtoString() Get a simple representation of this header. voidwriteHeader(WritableByteChannel out) Write the header data to the DBF file. 在Heade对象中要想获取字段的长度和精度主要是使用下列两个方法分别是getFieldLength(index)和getFieldDecimalCount(index)。在IDE中运行以上程序后可以在控制台中看到如下输出 名称 254 C 0
大类 254 C 0
中类 254 C 0
小类 254 C 0
地址 254 C 0
省 254 C 0
市 254 C 0
区 254 C 0
WGS84_经 19 F 11
WGS84_纬 19 F 11 可以看到这里不仅输出了数据的长度同时还输出了数据的精度。到此使用第二种方式来进行dbf文件的解析已经成功实现。
三、总结 以上就是本文的主要内容本文则重点讲解在Java当中如何使用GeoTools来进行属性表格的解析首先在Qgis中重点介绍属性表格的字段信息然后介绍一种常见的属性字段信息解析方式其次介绍基于dbf的属性信息解析方法直接解析dbf文件的方法在很多网络知识中很少见但是却非常有用比如在获取double类型的数值时想获取精度值就可以通过这种方式来获取。学习本文不仅更加熟悉GeoTools对属性表格的解析同时对于如何快速的将Shapefile的属性模型映射成空间库模型有更进一步的认识。行文仓促难免有许多不足之处如有不足还请各位专家博主在评论区留言指出不胜感激。