7.2.4 使用标准的格式:WKT、WKB和GML(1)
在第5章中我们讨论了能够在SDO_GEOMETRY类型和开放地理信息系统联盟(OGC)定义的标准格式之间进行转换的PL/SQL函数和方法。OGC的标准格式有:WKT(熟知文本)、WKB(熟知二进制)和GML(地理标识语言)。我们将对怎样在Java中执行这些转换做简要解释。
对这些格式进行操作的类都在oracle.spatial.util包中。SdoExport.java和SdoImport.java程序(可以从Apress站点下载)对WKT、WKB和GML格式的读写提供了功能齐全的例子。
1. 对WKT的读写
WKT格式是对几何体编码的一个结构化文本格式。它最初被设计为在不同环境间交换几何体的一种标准方法。点在WKT中可以被编码为:
- POINT(-111.870478 33.685992)
一个简单多边形可以编码为:
- POLYGON ((-119.308006 37.778061,..., -119.308006 37.778061))
我们将使用oracle.spatial.util包中WKT类的fromJGeometry()方法将JGeometry对象转换为WKT格式。注意,这个方法将生成一个字节数组,在将其写入到文件前,需要把它转换成一个字符串。如下所示:
- // Create a WKT processor
- WKT wkt = new WKT();
- ...
- // Convert the geometry to WKT
- String s = new String(wkt.fromJGeometry(geom));
也可以用WKT类中的toJGeometry方法把WKT字符串转回为JGeometry对象。这个方法的输入也是一个字节数组。过程如下所示:
- // Create a WKT processor
- WKT wkt = new WKT();
- ...
- // Convert the WKT to geometry
- JGeometry geom = wkt.toJGeometry(s.getBytes());
警告:
WKT和WKB格式没有提供任何的机制用来表示几何投影;也就是说,在将几何体转换成另一种格式时,这类信息将丢失。如果想保留这些信息,需要单独对其进行处理,同时用setSRID()方法把它回添到几何体中。
2. 对WKB的读写
顾名思义,WKB编码就是把几何体以二进制的方式编码,是一种比WKT更紧凑的格式。它的使用方法与前面的处理相似。WKB类中的fromJGeometry()方法也产生一个字节数组,你可以把该数组写到文件中。我们将向你展示怎样将其写入java DataOutputStream(在例子中称为ds)中,以便以便携的方式写入原始Java数据类型。
首先把JGeometry转换为WKB。这将产生一个字节数组。然后把字节数组的大小和几何体的SRID写入输出流。最后以适当的方式写入字节数组。
- // Create a WKB processor
- WKB wkb = new WKB(ByteOrder.BIG_ENDIAN);
- ...
- // Convert JGeometry to WKB
- byte[] b = wkb.fromJGeometry(geom);
- // First write the number of bytes in the array
- ds.writeInt(b.length);
- // Then write the SRID of the geometry
- ds.writeInt(geom.getSRID());
- // Then write the binary array
- ds.write(b);
注意,ByteOrder.BIG_ENDIAN参数表明要使用的二进制编码的类型:大尾段(big endian)或小尾段(litle endian)。默认生成大尾段编码。你需要使其与用来处理WKB工具所接受的编码相适应。注意,其中选择的编码方法本身是在二进制结果的第一个字节被标记的。
用WKB类中的toJGeometry()方法可以把WKB转换成JGeometry对象。这个方法仍用字节数组作为输入。下面的例子展示了这个过程。假设我们从先前的文件中读取数据,首先读取WKB的长度,然后读取几何体的SRID。接下来读取重建WKB所需的字节数。最后把WKB转换为JGeometry对象并用setSRID方法把SRID写回。
我们不需要指定将要使用的二进制编码的格式(大尾段或小尾段),因为toJGeometry()方法能够自动对编码进行识别并可以对两者进行透明的处理。
- // Create a WKB processor
- WKB wkb = new WKB();
- ...
- // Read the size of the byte array
- int n = ds.readInt();
- // Read the SRID of the geometry
- int srid = ds.readInt();
- // Read the byte array that contains the WKB
- byte[] b = new byte[n];
- int l = ds.read (b, 0, n);
- // Convert to JGeometry
- geom = wkb.toJGeometry(b);
- // Add the SRID
- geom.setSRID(srid);