java 利用jackcess和Esri geometry api解析mdb矢量数据

简要说明

在java,利用jackcess 和 Esri Geometry API,解析mdb的矢量数据;主要注意的地方是,记录矢量表的矢量字段的几何信息是在GDB_GeomColumns中;另外目前暂时无法找到原本数据的坐标系epsg code

maven依赖

		<dependency>
            <groupId>com.healthmarketscience.jackcess</groupId>
            <artifactId>jackcess</artifactId>
            <version>4.0.5</version>
        </dependency>
        
		<dependency>
            <groupId>com.esri.geometry</groupId>
            <artifactId>esri-geometry-api</artifactId>
            <version>2.2.4</version>
        </dependency>

样例代码

import com.esri.core.geometry.Geometry;
import com.esri.core.geometry.OperatorImportFromESRIShape;
import com.esri.core.geometry.ogc.OGCGeometry;
import com.healthmarketscience.jackcess.*;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ReadMDBWithJackcess {
    public static void main(String[] args) {
        String mdbPath = "C:\\Users\\xxxx\\Desktop\\xxxx.mdb";
        File file = new File(mdbPath);
        try (Database db = DatabaseBuilder.open(file)) {
            Map<String, Integer> tableFieldShapeTypeMap = getTableFieldShapeTypeMap(db);
            // 获取表名列表
            Set<String> tableNames = db.getTableNames();
            for (String tableName : tableNames) {
                // 打开表
                Table table = db.getTable(tableName);

                List<? extends Column> columns = table.getColumns();
                for (Column column : columns) {
                    System.out.println(column.getName() + "\t" + column.getType().toString());
                }
                System.out.println();

                // 读取所有行
                for (Row row : table) {
                    for (Column column : columns) {
                        Object value = row.get(column.getName());
                        //DataType.OLE 类型代表几何类型
                        if (value instanceof byte[] && DataType.OLE.toString().equals(column.getType().toString())) {
                            // 如果是字节数组,尝试解析为几何对象
                            byte[] shapeBytes = (byte[]) value;
                            if (shapeBytes != null && shapeBytes.length > 0) {
                                // 使用 Esri Geometry API 解析二进制数据
                                ByteBuffer buffer = ByteBuffer.wrap(shapeBytes).order(java.nio.ByteOrder.LITTLE_ENDIAN);
                                buffer.rewind(); // 确保从头开始读取

                                try {
                                    // 使用 OperatorImportFromESRIShape 解析 Shape 数据
                                    OperatorImportFromESRIShape opImportFromESRIShape = (OperatorImportFromESRIShape) OperatorImportFromESRIShape.local();

                                    Geometry.Type geometryTypeFromShapeType = getGeometryTypeFromShapeType(tableName, column.getName(), tableFieldShapeTypeMap);

                                    Geometry esriGeometry = opImportFromESRIShape.execute(0, geometryTypeFromShapeType ,buffer);

                                    if (esriGeometry != null) {
                                        // 将 Esri 几何对象转换为 OGC 几何对象
                                        OGCGeometry ogcGeometry = OGCGeometry.createFromEsriGeometry(esriGeometry, null);
                                        if (ogcGeometry != null) {
                                            // 输出 WKT 格式的几何数据
                                            System.out.print(ogcGeometry.asText() + "\t");
                                        } else {
                                            System.out.print("无法创建 OGC 几何对象\t");
                                        }
                                    } else {
                                        System.out.print("无效的几何数据\t");
                                    }
                                } catch (Exception e) {
                                    System.err.println("无法解析几何数据: " + e.getMessage());
                                }
                            } else {
                                System.out.print("无几何数据\t");
                            }
                        } else {
                            System.out.print(value + "\t");
                        }
                    }
                    System.out.println();
                }
                System.out.println("--------");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取mdb某个矢量表的几何类型
     * @param tableName
     * @param fieldName
     * @param tableFieldShapeTypeMap
     * @return
     */
    private static Geometry.Type getGeometryTypeFromShapeType(String tableName, String fieldName, Map<String, Integer> tableFieldShapeTypeMap) {
        if (!tableFieldShapeTypeMap.containsKey(tableName + "." + fieldName)) {
            return null;
        }
        Integer type = tableFieldShapeTypeMap.get(tableName + "." + fieldName);
        //暂时只支持点、折线、面,也大致通过真实数据推断GDB_GeomColumns表中记录的几何类型
        if (type.equals(1)) {
            return Geometry.Type.Point;
        }
        if (type.equals(3)) {
            return Geometry.Type.Polyline;
        }
        if (type.equals(4)) {
            return Geometry.Type.Polygon;
        }
        return null;
    }

    private static Map<String, Integer> getTableFieldShapeTypeMap(Database db) throws IOException {
        // 获取 GDB_GeomColumns 表
        Table geomColumnsTable = db.getTable("GDB_GeomColumns");

        // 创建一个映射,用于存储每个几何字段的几何类型
        Map<String, Integer> geometryTypeMap = new HashMap<>();

        // 读取 GDB_GeomColumns 表中的所有行
        for (Row row : geomColumnsTable) {
            String tableName = row.get("TableName").toString();
            String fieldName = row.get("FieldName").toString();
            int shapeType = ((Number) row.get("ShapeType")).intValue();

            // 将几何字段和几何类型存储在映射中
            geometryTypeMap.put(tableName + "." + fieldName, shapeType);
        }
        return geometryTypeMap;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值