ArcEngine字段小结
-
常用接口
- IField、IField2
- IFieldEdit、IFieldEdit2
- ISchemaLock
- IFields、IFields2
- IFieldsEdit、IFieldsEdit2
-
添加字段
创建字段并添加到字段集中
public IFields CreateFieldExample() { //1.新建IFields对象 IFields pFields = new FieldsClass(); //接口跳转到IFieldsEdit IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields; //2.新建IField对象 IField pField = new FieldClass(); //接口跳转到IFieldEdit对象上进行编辑 IFieldEdit2 pFieldEdit = (IFieldEdit2)pField; pFieldEdit.Name_2 = "FieldName";//Name属性只读,Name_2只写 pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString; pFieldEdit.Length_2 = 50; //3.将新建的IField对象添加到IFieldsEdit中 pFieldsEdit.AddField(pField); return pFields; } }将字段添加到已有的要素类中
public void AddFieldToFeatureClass(IFeatureClass featureClass, IField field) { ISchemaLock schemaLock = (ISchemaLock)featureClass;//创建模式锁对象 try { //修改为独占锁 schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); //判断字段是否存在,存在则返回,不存在则添加 if (featureClass.FindField(field.Name) == -1) { // 添加字段 featureClass.AddField(field); } } catch (Exception ex) { // 输出异常 Console.WriteLine(ex.Message); } finally { // 修改为共享锁 schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } }获取创建要素类所需的最少字段
public IFields CreateFieldsCollectionForFeatureClass(ISpatialReference spatialReference) { //创建IFeatureClassDescription接口 IFeatureClassDescription pFeaClassDesc = new FeatureClassDescriptionClass(); IObjectClassDescription pObjClassDesc = (IObjectClassDescription)pFeaClassDesc; // 获取所需的字段集合 IFields pFields = pObjClassDesc.RequiredFields; // 获取几何字段 int iShapeFieldIndex = pFields.FindField(pFeaClassDesc.ShapeFieldName); IField pShapeField = pFields.get_Field(iShapeFieldIndex); // 获取几何定义 IGeometryDef pGeometryDef = pShapeField.GeometryDef; IGeometryDefEdit pGeometryDefEdit = (IGeometryDefEdit)pGeometryDef; // 修改要素类的集合类型为线(默认为面) pGeometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolyline; pGeometryDefEdit.HasM_2 = true; pGeometryDefEdit.GridCount_2 = 1; //设置格网大小为(0,0) pGeometryDefEdit.set_GridSize(0, 0); //设置坐标系 pGeometryDefEdit.SpatialReference_2 = spatialReference; // 创建IFieldsEdit对象 IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields; // 创建自定义的字段 IField incomeField = new FieldClass(); IFieldEdit incomeFieldEdit = (IFieldEdit)incomeField; incomeFieldEdit.AliasName_2 = "Average income for 1999-2000"; incomeFieldEdit.Editable_2 = true;//可编辑 incomeFieldEdit.IsNullable_2 = false;//不允许为空 incomeFieldEdit.Name_2 = "average_income";//字段名称 incomeFieldEdit.Precision_2 = 2;//字段精度 incomeFieldEdit.Scale_2 = 5; incomeFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;//字段类型 //添加自定义字段 pFieldsEdit.AddField(incomeField); return pFields; }验证字段
public IFields ValidateFieldsForWorkspace(IFields fields, IWorkspace workspace) { // 创建IFieldChecker对象. IFieldChecker pFieldChecker = new FieldCheckerClass(); pFieldChecker.ValidateWorkspace = workspace; // 验证字段集 IEnumFieldError enumFieldError = null; IFields validatedFields = null; pFieldChecker.Validate(fields, out enumFieldError, out validatedFields); // 显示字段错误 IFieldError fieldError = null; enumFieldError.Reset(); while ((fieldError = enumFieldError.Next()) != null) { IField errorField = fields.get_Field(fieldError.FieldIndex); Console.WriteLine("Field '{0}': Error '{1}'", errorField.Name, fieldError.FieldError); } //返回验证的字段 return validatedFields; } -
修改字段
修改字段有两种方法,一种是调用接口IFieldEdit2,另外一种是调用GP工具(ArcMap中位置:Data Management Tools\Fields\AlterField)。
//更新字段的第一种方法,调用IFieldEdit2接口(属性后面带“_2”的代表只写,不带“_2”的代表只读) public void UpdateField(IField pInField) { IFieldEdit2 pFieldEdit = pInField as IFieldEdit2; pFieldEdit.Name_2 = "NewName"; pFieldEdit.AliasName_2 = "NewAlias"; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString; pFieldEdit.Length_2 = pFieldEdit.Length + 50; pFieldEdit.IsNullable_2 = !pFieldEdit.IsNullable; //...... } //更新字段的第二种方法,调用GP工具,代码略 -
删除字段
删除字段有两种方法,一种是调用接口IFieldsEdit,另外一种是调用GP工具,(ArcMap中位置:Data Management Tools\Fields\DeleteField)。
//删除字段的第一种方法,调用IFieldsEdit接口 public void DeleteField(IFields pInFields,IField pDeleteField) { IFieldsEdit pFieldsEdit = pInFields as IFieldsEdit; pFieldsEdit.DeleteAllFields();//删除全部字段 pFieldsEdit.DeleteField(pDeleteField);//删除指定字段 } //官方版示例,开始模式锁,然后再删除字段 public void DeleteField(IObjectClass objectClass, String fieldName) { // Get the field to be deleted. int fieldIndex = objectClass.FindField(fieldName); IField field = objectClass.Fields.get_Field(fieldIndex); // Cast to the ISchemaLock interface. ISchemaLock schemaLock = (ISchemaLock)objectClass; try { // Get an exclusive schema lock on the object class. schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); // Alter the class extension for the class. objectClass.DeleteField(field); } catch (Exception e) { // An error was raised; therefore, notify the user. Console.WriteLine(e.Message); } finally { // Since the Finally block is always called, the exclusive lock is demoted // to a shared lock after the field is deleted and after an error is raised. schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } } //删除字段的第二种方法,调用GP工具,代码略 -
字段批量赋值
字段批量赋值有三种方法:①遍历数据,然后用游标查询进行赋值 ②利用GP工具CalculateField进行批量赋值 ③利用IWorkspace的ExcuteSQL执行Update语句进行批量赋值。(具体代码略)
效率对比:③>②>① -
遍历字段
//遍历字段 public void TraversalQuery(IFields pFields) { for (int i = 0; i < pFields.FieldCount; i++) { IField pField = pFields.get_Field(i); //...... } } //获取字段的总数 public int GetFieldsCount(IFields pFields) { IFieldsEdit pFieldsEdit = pFields as IFieldsEdit; return pFieldsEdit.FieldCount; } -
读取字段值列表
public List<string> GetFieldUniqueValue(ITable pTable, string sFieldName, IQueryFilter pQueryFilter = null) { if (pTable == null || pTable.FindField(sFieldName) < 0) { return null; } List<string> valuesList = new List<string>(); using (ComReleaser pComReleaser = new ComReleaser()) { ICursor pCursor = pTable.Search(pQueryFilter, true); pComReleaser.ManageLifetime(pCursor); IDataStatistics pDataStats = new DataStatisticsClass(); pComReleaser.ManageLifetime(pDataStats); pDataStats.Cursor = pCursor; pDataStats.Field = sFieldName; IEnumerator pEnumValues = pDataStats.UniqueValues; pComReleaser.ManageLifetime(pEnumValues); pEnumValues.Reset(); while (pEnumValues.MoveNext()) { object objValue = pEnumValues.Current; if (objValue == null || Convert.IsDBNull(objValue)) { continue; } valuesList.Add(objValue.ToString()); } } return valuesList; } public List<string> GetFieldUniqueValue(IFeatureWorkspace pFeaWs, string sTableName, string sFldName, string sWhere = "") { List<string> values = new List<string>(); using (ComReleaser pComreleaser = new ComReleaser()) { IQueryDef pQueryDef = pFeaWs.CreateQueryDef(); pComreleaser.ManageLifetime(pQueryDef); pQueryDef.Tables = sTableName; pQueryDef.SubFields = "DISTINCT(" + sFldName + ")"; if (sWhere != "") { pQueryDef.WhereClause = sWhere; } ICursor pCursor = pQueryDef.Evaluate(); IRow pRow = null; while ((pRow = pCursor.NextRow()) != null) { string sValue = CommonAPI.ConvertToString(pRow.get_Value(0)); values.Add(sValue); } return values; } } -
字段值统计
参考https://www.cnblogs.com/lauer0246/archive/2008/08/01/1258109.html
-
blob字段的读写
//读取blob字段到字符串中 public string ReadStringFromBlob(object objValue) { string sResault = ""; IMemoryBlobStreamVariant pMemoryBlobStreamVariant = objValue as IMemoryBlobStreamVariant; if (pMemoryBlobStreamVariant != null) { pMemoryBlobStreamVariant.ExportToVariant(out objValue); sResault = Encoding.Default.GetString(objValue as byte[]); } return sResault; } //读取Blob字段中的二进制字节数组 public byte[] ReadBytesFromBlob(object objValue) { IMemoryBlobStreamVariant pMemoryBlobStreamVariant = objValue as IMemoryBlobStreamVariant; if (pMemoryBlobStreamVariant != null) { pMemoryBlobStreamVariant.ExportToVariant(out objValue); } byte[] bytes = objValue as byte[]; return bytes; } //将字符串写入Blob流对象 public IMemoryBlobStream WriteStringToBlob(string sValue) { IMemoryBlobStream blobStream = new MemoryBlobStreamClass(); if (!string.IsNullOrWhiteSpace(sValue)) { object objValue = Encoding.Default.GetBytes(sValue); (blobStream as IMemoryBlobStreamVariant).ImportFromVariant(objValue); } return blobStream; } //将字节数组写入Blob流对象 public IMemoryBlobStream WriteBytesToBlob(byte[] bytes) { IMemoryBlobStream blobStream = new MemoryBlobStreamClass(); (blobStream as IMemoryBlobStreamVariant).ImportFromVariant(bytes); return blobStream; } //将Object对象写入到Blob字段中 public void SaveBlobValue(IRowBuffer rowBuffer, int iFieldIndex, object value) { if (value is IPersistStream) { IMemoryBlobStream pBlobStream = new MemoryBlobStreamClass(); (value as IPersistStream).Save(pBlobStream, 0); rowBuffer.set_Value(iFieldIndex, pBlobStream); } else { IMemoryBlobStream pBlobStream = new MemoryBlobStreamClass(); rowBuffer.set_Value(iFieldIndex, pBlobStream); } } -
字段的拷贝
public IField CopyField(IField pInField) { IField pOutField = (pInField as ESRI.ArcGIS.esriSystem.IClone).Clone() as IField; return pOutField; }
Maven
简介
java包管理和构建工具
一个使用Maven管理的普通的Java项目,它的目录结构默认如下:
a-maven-project
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ ├── java
│ └── resources
└── target
pom.xml是maven的项目描述文件
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>hello</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
...
</properties>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
依赖管理
依赖关系
Maven定义了几种依赖关系,分别是compile、test、runtime和provided:
| scope | 说明 | 示例 |
|---|---|---|
| compile | 编译时需要用到该jar包(默认) | commons-logging |
| test | 编译Test时需要用到该jar包 | junit |
| runtime | 编译时不需要,但运行时需要用到 | mysql |
| provided | 编译时需要用到,但运行时由JDK或某个服务器提供 | servlet-api |
其中,默认的compile是最常用的,Maven会把这种类型的依赖直接放入classpath。
test依赖表示仅在测试时使用,正常运行时并不需要。最常用的test依赖就是JUnit:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
runtime依赖表示编译时不需要,但运行时需要。最典型的runtime依赖是JDBC驱动,例如MySQL驱动:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<scope>runtime</scope>
</dependency>
provided依赖表示编译时需要,但运行时不需要。最典型的provided依赖是Servlet API,编译的时候需要,但是运行时,Servlet服务器内置了相关的jar,所以运行期不需要:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
Maven并不会每次都从中央仓库下载jar包。一个jar包一旦被下载过,就会被Maven自动缓存在本地目录(用户主目录的.m2目录),所以,除了第一次编译时因为下载需要时间会比较慢,后续过程因为有本地缓存,并不会重复下载相同的jar包。
唯一ID
对于某个依赖,Maven只需要3个变量即可唯一确定某个jar包:
- groupId:属于组织的名称,类似Java的包名;
- artifactId:该jar包自身的名称,类似Java的类名;
- version:该jar包的版本。
通过上述3个变量,即可唯一确定某个jar包。Maven通过对jar包进行PGP签名确保任何一个jar包一经发布就无法修改。修改已发布jar包的唯一方法是发布一个新版本。
构建流程
在实际开发过程中,经常使用的命令有:
mvn clean:清理所有生成的class和jar;
mvn clean compile:先清理,再执行到compile;
mvn clean test:先清理,再执行到test,因为执行test前必须执行compile,所以这里不必指定compile;
mvn clean package:先清理,再执行到package。
大多数phase在执行过程中,因为通常没有在pom.xml中配置相关的设置,所以这些phase什么事情都不做。
经常用到的phase其实只有几个:
- clean:清理
- compile:编译
- test:运行测试
- package:打包
使用插件
如果标准插件无法满足需求,还可以使用自定义插件。使用自定义插件的时候,需要声明。例如,使用maven-shade-plugin可以创建一个可执行的jar,要使用这个插件,需要在pom.xml中声明它:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
自定义插件往往需要一些配置,例如,maven-shade-plugin需要指定Java程序的入口,它的配置是:
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.itranswarp.learnjava.Main</mainClass>
</transformer>
</transformers>
</configuration>
注意,Maven自带的标准插件例如compiler是无需声明的,只有引入其它的插件才需要声明。
模块管理
对于Maven工程来说,原来是一个大项目:
single-project
├── pom.xml
└── src
可以看出来,模块A和模块B的pom.xml高度相似,因此,可以提取出共同部分作为parent:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>parent</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
注意到parent的<packaging>是pom而不是jar,因为parent本身不含任何Java代码。编写parent的pom.xml只是为了在各个模块中减少重复的配置。现在的整个工程结构如下:
multiple-project
├── pom.xml
├── parent
│ └── pom.xml
├── module-a
│ ├── pom.xml
│ └── src
├── module-b
│ ├── pom.xml
│ └── src
└── module-c
├── pom.xml
└── src
这样模块A就可以简化为:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>module-a</artifactId>
<packaging>jar</packaging>
<name>module-a</name>
</project>
模块B、模块C都可以直接从parent继承,大幅简化了pom.xml的编写。
如果模块A依赖模块B,则模块A需要模块B的jar包才能正常编译,需要在模块A中引入模块B:
...
<dependencies>
<dependency>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>module-b</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
最后,在编译的时候,需要在根目录创建一个pom.xml统一编译:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>build</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>build</name>
<modules>
<module>parent</module>
<module>module-a</module>
<module>module-b</module>
<module>module-c</module>
</modules>
</project>
这样,在根目录执行mvn clean package时,Maven根据根目录的pom.xml找到包括parent在内的共4个<module>,一次性全部编译。
本文总结了ArcEngine中字段操作的方法,包括字段的创建、添加、修改、删除及批量赋值等关键步骤,并介绍了如何使用接口实现这些操作。此外,还提供了字段值的统计和读写方法。

被折叠的 条评论
为什么被折叠?



