基于Java的GeoTools对Shapefile文件属性信息深度解析
目录
前言
一、Shapefile的属性列表信息
1、属性表格信息
2、属性表格包含的要素
二、GeoTools对属性表格的解析
1、常规解析方法
2、基于dbf文件的属性信息读取
三、总结
前言
ESRI Shapefile(shp),或简称shapefile,是美国环境系统研究所公司(ESRI)开发的一种空间数据开放格式。该文件格式已经成为了地理信息软件界的一个开放标准,这表明ESRI公司在全球的地理信息系统市场的重要性。Shapefile也是一种重要的交换格式,它能够在ESRI与其他公司的产品之间进行数据互操作。Shapefile文件用于描述几何体对象:点,折线与多边形。例如,Shapefile文件可以存储井、河流、湖泊等空间对象的几何位置。除了几何位置,shp文件也可以存储这些空间对象的属性,例如一条河流的名字,一个城市的温度等等。

        Shapefile属于一种矢量图形格式,它能够保存几何图形的位置及相关属性。但这种格式没法存储地理数据的拓扑信息。Shapefile在九十年代初的ArcView GIS的第二个版本被首次应用。许多自由的程序或商业的程序都可以读取Shapefile。Shapefile是一种比较原始的矢量数据存储方式,它仅仅能够存储几何体的位置数据,而无法在一个文件之中同时存储这些几何体的属性数据。因此,Shapefile还必须附带一个二维表用于存储Shapefile中每个几何体的属性信息。Shapefile中许多几何体能够代表复杂的地理事物,并为他们提供强大而精确的计算能力。
         Shapefile文件指的是一种文件存储的方法,实际上该种文件格式是由多个文件组成的。其中,要组成一个Shapefile,有三个文件是必不可少的,它们分别是".shp", ".shx"与 ".dbf"文件。表示同一数据的一组文件其文件名前缀应该相同。例如,存储一个关于湖的几何与属性数据,就必须有lake.shp,lake.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 | 名称 | 具体的字段名称,如name | 
| 2 | 别名 | 类比于关系数据库的字段别名 | 
| 3 | 类型 | 数据类型,比如QString | 
| 4 | 类型名 | 数据类型名,比如String,Real | 
| 5 | 长度 | 字段的长度,比如:255 | 
| 6 | 精度 | double等类型的精度,如11 | 
| 7 | 注解 | 其它辅助信息 | 
有了上面的信息之后,我们也可以根据属性表格来进行空间表的创建,这样管理起来也比较方便。在数据库中定义好每一个列的数据信息之后,就可以将具体的空间信息填充到每一行中,这时候可能就需要外业和内业的工作人员通力配合。

在了解上面的基本信息后,在下面的章节中,我们就要进行属性表格的深度解析操作。
二、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);// 获取属性名List<String> attributeNames = featureType.getAttributeDescriptors().stream().map(attr -> attr.getLocalName()).collect(Collectors.toList());System.out.println("Attributes: " + attributeNames);System.out.println("以下是属性信息的深度解析:----------------------------------------");List<AttributeDescriptor> 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());List<Filter> 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 Double<Double>
restrictions=[ length([.]) <= 19 ]
name=WGS84_纬	LocalName=WGS84_纬	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 Type | Method | Description | 
|---|---|---|
void | close() |   Clean up all resources associated with this reader.Highly recomended.  | 
protected int | fill(ByteBuffer buffer, ReadableByteChannel channel) | |
DbaseFileHeader | getHeader() |   Get the header from this file.  | 
boolean | hasNext() |   Query the reader as to whether there is another record.  | 
String | id() |   An id for the reader.  | 
static void | main(String[] args) | |
void | read() |   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.  | 
Object | readField(int fieldNum) |   Reads a single field from the current record and returns it.  | 
DbaseFileReader.Row | readRow() | |
void | skip() |   Skip the next record.  | 
void | transferTo(DbaseFileWriter writer) |   Transfer, by bytes, the next record to the writer.  | 
想要获取属性就是通过获取Head对象即可实现属性列表的深度解析。返回DbaseFileHead,它的方法如下表所示:
| Modifier and Type | Method | Description | 
|---|---|---|
void | addColumn(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.  | 
int | getFieldDecimalCount(int inIndex) |   Get the decimal count of this field.  | 
int | getFieldLength(int inIndex) |   Returns the field length in bytes.  | 
String | getFieldName(int inIndex) |   Get the field name.  | 
char | getFieldType(int inIndex) |   Get the character class of the field.  | 
int | getHeaderLength() |   Get the length of the header  | 
int | getLargestFieldSize() |   Get the largest field size of this table.  | 
Date | getLastUpdateDate() |   Get the date this file was last updated.  | 
long | getLengthForRecords(int records) |   Returns the expected file size for the given number of records in the file  | 
int | getNumFields() |   Return the number of fields in the records.  | 
int | getNumRecords() |   Return the number of records in the file  | 
int | getRecordLength() |   Get the length of the records in bytes.  | 
void | readHeader(ByteBuffer in) |   Read the header data from the DBF file.  | 
void | readHeader(ReadableByteChannel channel) |   Read the header data from the DBF file.  | 
int | removeColumn(String inFieldName) |   Remove a column from this DbaseFileHeader.  | 
void | setNumRecords(int inNumRecords) |   Set the number of records in the file  | 
String | toString() |   Get a simple representation of this header.  | 
void | writeHeader(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的属性模型映射成空间库模型有更进一步的认识。行文仓促,难免有许多不足之处,如有不足还请各位专家博主在评论区留言指出,不胜感激。
相关文章:
基于Java的GeoTools对Shapefile文件属性信息深度解析
目录 前言 一、Shapefile的属性列表信息 1、属性表格信息 2、属性表格包含的要素 二、GeoTools对属性表格的解析 1、常规解析方法 2、基于dbf文件的属性信息读取 三、总结 前言 ESRI Shapefile(shp),或简称shapefile,是美…...
付费计量系统实体和接口(1)
13.System entities and interfaces 系统实体和接口 See also Clause 4 for a discussion on general concepts and Clause 5 for generic entity model. 参见条目 4 讨论总体概念、条目 5 通用实体模型。 An entity specification should specify the embodied functions and …...
网易博客旧文----bacnet学习系列之四----VTS的初步使用
bacnet学习系列之四----VTS的初步使用 2014-02-07 13:32:28| 分类: BACnet | 标签: |举报 |字号大中小 订阅 这是一个测试用 的工具,而且是开放源码的,下载地址为:VTS下载官网 也可以从我的网盘下载 VTS下载 我用的是…...
SpringIoC容器的初识
一、SpringIoC容器的介绍 Spring IoC 容器,负责实例化、配置和组装 bean(组件)。容器通过读取配置元数据来获取有关要实例化、配置和组装组件的指令。配置元数据以 XML、Java 注解或 Java 代码形式表现。它允许表达组成应用程序的组件以及这…...
队列的实现与讲解
一.概念与结构 1.概念 只允许在⼀端进行插⼊数据操作,在另⼀端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)  入队列:进⾏插⼊操作的⼀端称为队尾  出队列:进⾏删除操作的⼀端称为队头 注意&…...
hbuilderx+uniapp+Android健身房管理系统 微信小程序z488g
目录 项目介绍支持以下技术栈:具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是:数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 用户功能…...
自动驾驶-参考线生成
为什么要进行参考线生成? apollo在routing模块,已经得到的全局路径,但是其不能直接作为局部路径规划的参考线,这是因为: routing给出的全局路径过长;routing是基于高精地图给出的路径,高精地图…...
厂商资源分享网站
新华三(H3C)是一家中国知名的网络设备供应商,提供网络设备、网络解决方案和云计算服务。公司成立于2003年,是华为公司和惠普公司合资的企业,总部位于中国深圳。 华为(Huawei)是一家全球知名的电…...
【ONE·Web || HTML】
总言 主要内容:HTML基本知识入门,主要介绍了常见的一些标签使用,以及简单案例演示。 文章目录 总言0、前置说明1、认识HTML1.1、是什么1.2、初识 HTML 标签、HTML 文件基本结构1.2.1、相关说明1.2.2、vscode如何快速生成代码 2、HT…...
MongoDB的安装与增删改查基本操作
MongoDB是一种非关系型数据库,是NoSQL语言,但是又是最接近关系型数据库的。内部存储不是表结构,但是可以对数据进行表结构的操作。 一、安装 在官网:Download MongoDB Community Server | MongoDB下载系统对应的版本进行安装即可 二、编辑器 在安装MongoDB后会自带一个编…...
Python水循环标准化对比算法实现
🎯要点 算法区分不同水循环数据类型:地下水、河水、降水、气温和其他,并使用相应标准化降水指数、标准化地下水指数、标准化河流水位指数和标准化降水蒸散指数。绘制和计算特定的时间序列比较统计学相关性。使用相关矩阵可视化集水区和显示空…...
【TypeScript】知识点梳理(一)
#国庆快乐!来点干货~ # #项目中团队总结生产问题,40%是类型相关问题,可见TS的重要性与向好趋势# TS是JS的超集 类型 Number、String、Boolean 首字母大小写,类型有区别,譬如: string是基元(原始…...
DMA方式在执行中断处理程序时不中断现行程序吗
DMA方式在执行中断处理程序时会中断现行程序,但DMA数据传输过程本身不中断现行程序。以下是对DMA方式及其中断处理程序的详细解释: DMA方式的基本特点 DMA(Direct Memory Access,直接存储器存取)方式是一种由硬件直接…...
Redis:string类型
Redis:string类型 string命令设置与读取SETGETMSETMGET 数字操作INCRINCRBYDECRDECRBYINCRBYFLOAT 字符串操作APPENDSTRLENGETRANGESETRANGE 内部编码intembstrraw 在Redis中,字符串string存储的是二进制,以byte为单位,输入的二进…...
【C++ STL】手撕vector,深入理解vector的底层
vector的模拟实现 前言一.默认成员函数1.1常用的构造函数1.1.1默认构造函数1.1.2 n个 val值的构造函数1.1.3 迭代器区间构造1.1.4 initializer_list 的构造 1.2析构函数1.3拷贝构造函数1.4赋值运算符重载 二.元素的插入,删除,查找操作2.1 operator[]重载函数2.2 push_back函数:…...
【Android】CarWatchDog I/O监控服务
Android Car WatchDog I/O监控服务 背景: 某基于Android 13的车载系统。 某天长时间测试一款3方(非SystemApp)时,该款应用偶发闪退现象。 通过日志分析,发现应用被系统的 Car WatchDog(喂狗服务ÿ…...
如何使用 Django 框架进行用户认证的详细指南,涵盖用户注册和登录功能的实现。
当然!下面是关于如何使用 Django 框架进行用户认证的详细指南,涵盖用户注册和登录功能的实现。 掌握 Django 用户认证的艺术 Django 是一个强大的 Python Web 框架,以其灵活性和高效性著称。无论你是新手还是经验丰富的开发者,理解和实现用户认证都是 Web 开发中的一项核心…...
C++ 语言特性21 - 别名模板
一:概述 别名模板是 C11 引入的,用于为一个模板类型定义别名,从而简化复杂的模板类型定义。它结合了 using 关键字,可以对模板类型进行重新命名,使代码更加简洁和可读。 1. 作用 定义模板类型的别名。简化复杂的模板类…...
Jenkins pipeline配置示例
前提条件:已经安装Jenkins并能正常启动 如果Jenkins安装启动遇到问题可以参考: 1.创建pipeline 点击新建项目: 输入名称,选择pipeline: 进入配置页面,如果要配置GitHub Webhook要勾选:<fo…...
Navicat for MySQL 常见问题
一、 创建连接失败问题 创建连接后,报错:1251 -Client does not support authentication protocal by server;consider upgrading MySQL client 原因:环境冲突 解决办法 : windowsR 打开 services.msc 找S开头:SQ…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
