Ein relativ junger Stern am Himmel der Vektordatenformate im GIS-Bereich ist die FlatGeobuf-Datei. Sie basiert auf FlatBuffers und hält Vektor-Geodaten in einem Binärformat vor (Dateiendung .fgb). Enthalten sind Geometrien (genannt "Features", also z.B. Polygone, beschrieben durch eine Reihe von Punkten) und Attribute (Beschreibungen zu den Features, im Grunde eine Tabelle mit so vielen Zeilen, wie Features enthalten sind, und mehreren Spalten für die Variablen).
Dazu gibt es noch zwei Metadaten: Erstens, der Name des Datensatzes (ein einfacher String) und das Geokoordinatensystem ("CRS", coordinate reference system) im WKT-Format, also ebenfalls als String. Zum Handling von FlatGeobuf-Daten nutze ich in C# das Package "FlatGeobuf", das seinerseits auf "NetTopologySuite" aufsetzt. Lädt man damit eine .fgb-Datei und deserialisiert sie, erhält man ein .NET-Listobjekt (so eine Collection), mit der man ziemlich komfortabel auf die Geometrien und Attribute zugreifen kann.
Dabei scheint es allerdings so, als gingen die Metainformationen Name und CRS verloren. Nirgendwo in der Datenstruktur finde ich diese Informationen. Also dachte ich, ich kratze mir die Strings einfach selbst aus dem Header der Datei, wo sie einfach so drin stehen. Das klappt leidlich.
Mein Problem ist, dass ich keine gute Dokumentation zum Header finde. Hier steht bloß was zu den Magic Bytes sowie die Information, dass danach der Header kommt. Klickt man dort auf den Link zum Header, findet man das hier, was mir nicht hilft und meiner Ansicht nach sogar falsch ist, weil demnach der Datensatzname im Header vor der Angabe der Anzahl der in der Datei enthaltenen Features kommen soll, tatsächlich steht der Name aber danach in der Datei. Die Anzahl und Struktur der dazwischenliegenden Informationen stimmt auch nicht.
Ich würde gern den Header etwas besser verstehen. Leider gibt's offenbar nicht einfach Offsets, die mir die Startpositionen der nullterminierten Strings verraten. Wie komme ich hier weiter? Hat jemand von Euch ein besseres Reverse-Engineering-Auge als ich?
Hier mal der Header einer gültigen .fgb-Datei. Man sieht zuerst die acht Bytes für die Magic Number, dann kommt an Offset 0x98 der Name, bei Offset 0xCC beginnt dann der WKT-String für das CRS. Bei 0x0234 stehen die Spaltenüberschriften der Attributtabelle, danach kommen die eigentlichen Binärdaten. Die Datei enthält übrigens 3221 Features (= 0x0C95), das steht bei Offset 0x48, wie man sieht in Little Endian. Soweit ich weiß, sind alle Werte als 32-Bit-Typen zu verstehen (also immer vier Bytes).
Hier der Hexdump als Bild:
Und hier die rohen Daten:
Dazu gibt es noch zwei Metadaten: Erstens, der Name des Datensatzes (ein einfacher String) und das Geokoordinatensystem ("CRS", coordinate reference system) im WKT-Format, also ebenfalls als String. Zum Handling von FlatGeobuf-Daten nutze ich in C# das Package "FlatGeobuf", das seinerseits auf "NetTopologySuite" aufsetzt. Lädt man damit eine .fgb-Datei und deserialisiert sie, erhält man ein .NET-Listobjekt (so eine Collection), mit der man ziemlich komfortabel auf die Geometrien und Attribute zugreifen kann.
Dabei scheint es allerdings so, als gingen die Metainformationen Name und CRS verloren. Nirgendwo in der Datenstruktur finde ich diese Informationen. Also dachte ich, ich kratze mir die Strings einfach selbst aus dem Header der Datei, wo sie einfach so drin stehen. Das klappt leidlich.
Mein Problem ist, dass ich keine gute Dokumentation zum Header finde. Hier steht bloß was zu den Magic Bytes sowie die Information, dass danach der Header kommt. Klickt man dort auf den Link zum Header, findet man das hier, was mir nicht hilft und meiner Ansicht nach sogar falsch ist, weil demnach der Datensatzname im Header vor der Angabe der Anzahl der in der Datei enthaltenen Features kommen soll, tatsächlich steht der Name aber danach in der Datei. Die Anzahl und Struktur der dazwischenliegenden Informationen stimmt auch nicht.
Ich würde gern den Header etwas besser verstehen. Leider gibt's offenbar nicht einfach Offsets, die mir die Startpositionen der nullterminierten Strings verraten. Wie komme ich hier weiter? Hat jemand von Euch ein besseres Reverse-Engineering-Auge als ich?
Hier mal der Header einer gültigen .fgb-Datei. Man sieht zuerst die acht Bytes für die Magic Number, dann kommt an Offset 0x98 der Name, bei Offset 0xCC beginnt dann der WKT-String für das CRS. Bei 0x0234 stehen die Spaltenüberschriften der Attributtabelle, danach kommen die eigentlichen Binärdaten. Die Datei enthält übrigens 3221 Features (= 0x0C95), das steht bei Offset 0x48, wie man sieht in Little Endian. Soweit ich weiß, sind alle Werte als 32-Bit-Typen zu verstehen (also immer vier Bytes).
Hier der Hexdump als Bild:
Und hier die rohen Daten:
Code:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 66 67 62 03 66 67 62 00 DC 02 00 00 24 00 00 00 fgb.fgb.Ü...$...
00000010 00 00 00 00 00 00 1A 00 20 00 08 00 0C 00 07 00 ........ .......
00000020 00 00 00 00 00 00 00 00 10 00 18 00 00 00 14 00 ................
00000030 1A 00 00 00 00 00 00 06 5C 00 00 00 30 00 00 00 ........\...0...
00000040 10 00 00 00 70 00 00 00 95 0C 00 00 00 00 00 00 ....p...•.......
00000050 06 00 00 00 78 02 00 00 50 02 00 00 34 02 00 00 ....x...P...4...
00000060 18 02 00 00 FC 01 00 00 E0 01 00 00 04 00 00 00 ....ü...à.......
00000070 90 2C 60 02 B7 64 66 C0 5D 13 D2 1A 83 E2 31 40 .,`.·dfÀ].Ò.ƒâ1@
00000080 59 DD EA 39 E9 78 66 40 7E F5 84 5A 90 D6 51 40 YÝê9éxf@~õ„Z.ÖQ@
00000090 00 00 00 00 0A 00 00 00 55 53 63 6F 75 6E 74 69 ........UScounti
000000A0 65 73 00 00 00 00 0E 00 14 00 04 00 08 00 0C 00 es..............
000000B0 00 00 10 00 0E 00 00 00 84 01 00 00 AD 10 00 00 ........„.......
000000C0 70 01 00 00 04 00 00 00 62 01 00 00 47 45 4F 47 p.......b...GEOG
000000D0 43 52 53 5B 22 4E 41 44 38 33 22 2C 44 41 54 55 CRS["NAD83",DATU
000000E0 4D 5B 22 4E 6F 72 74 68 20 41 6D 65 72 69 63 61 M["North America
000000F0 6E 20 44 61 74 75 6D 20 31 39 38 33 22 2C 45 4C n Datum 1983",EL
00000100 4C 49 50 53 4F 49 44 5B 22 47 52 53 20 31 39 38 LIPSOID["GRS 198
00000110 30 22 2C 36 33 37 38 31 33 37 2C 32 39 38 2E 32 0",6378137,298.2
00000120 35 37 32 32 32 31 30 31 2C 4C 45 4E 47 54 48 55 57222101,LENGTHU
00000130 4E 49 54 5B 22 6D 65 74 72 65 22 2C 31 5D 5D 5D NIT["metre",1]]]
00000140 2C 50 52 49 4D 45 4D 5B 22 47 72 65 65 6E 77 69 ,PRIMEM["Greenwi
00000150 63 68 22 2C 30 2C 41 4E 47 4C 45 55 4E 49 54 5B ch",0,ANGLEUNIT[
00000160 22 64 65 67 72 65 65 22 2C 30 2E 30 31 37 34 35 "degree",0.01745
00000170 33 32 39 32 35 31 39 39 34 33 33 5D 5D 2C 43 53 32925199433]],CS
00000180 5B 65 6C 6C 69 70 73 6F 69 64 61 6C 2C 32 5D 2C [ellipsoidal,2],
00000190 41 58 49 53 5B 22 6C 61 74 69 74 75 64 65 22 2C AXIS["latitude",
000001A0 6E 6F 72 74 68 2C 4F 52 44 45 52 5B 31 5D 2C 41 north,ORDER[1],A
000001B0 4E 47 4C 45 55 4E 49 54 5B 22 64 65 67 72 65 65 NGLEUNIT["degree
000001C0 22 2C 30 2E 30 31 37 34 35 33 32 39 32 35 31 39 ",0.017453292519
000001D0 39 34 33 33 5D 5D 2C 41 58 49 53 5B 22 6C 6F 6E 9433]],AXIS["lon
000001E0 67 69 74 75 64 65 22 2C 65 61 73 74 2C 4F 52 44 gitude",east,ORD
000001F0 45 52 5B 32 5D 2C 41 4E 47 4C 45 55 4E 49 54 5B ER[2],ANGLEUNIT[
00000200 22 64 65 67 72 65 65 22 2C 30 2E 30 31 37 34 35 "degree",0.01745
00000210 33 32 39 32 35 31 39 39 34 33 33 5D 5D 2C 49 44 32925199433]],ID
00000220 5B 22 45 50 53 47 22 2C 34 32 36 39 5D 5D 00 00 ["EPSG",4269]]..
00000230 05 00 00 00 4E 41 44 38 33 00 00 00 04 00 00 00 ....NAD83.......
00000240 45 50 53 47 00 00 00 00 84 FF FF FF 00 00 00 0B EPSG....„ÿÿÿ....
00000250 04 00 00 00 04 00 00 00 4C 53 41 44 00 00 00 00 ........LSAD....
00000260 9C FF FF FF 00 00 00 0B 04 00 00 00 04 00 00 00 œÿÿÿ............
00000270 4E 41 4D 45 00 00 00 00 B4 FF FF FF 00 00 00 0B NAME....´ÿÿÿ....
00000280 04 00 00 00 05 00 00 00 53 54 41 54 45 00 00 00 ........STATE...
00000290 CC FF FF FF 00 00 00 0B 04 00 00 00 04 00 00 00 Ìÿÿÿ............
000002A0 46 49 50 53 00 00 00 00 E4 FF FF FF 00 00 00 0B FIPS....äÿÿÿ....
000002B0 04 00 00 00 0A 00 00 00 43 4F 55 4E 54 59 5F 46 ........COUNTY_F
000002C0 49 50 00 00 08 00 0C 00 08 00 07 00 08 00 00 00 IP..............
000002D0 00 00 00 0B 04 00 00 00 0A 00 00 00 53 54 41 54 ............STAT
000002E0 45 5F 46 49 50 53 00 00 90 2C 60 02 B7 64 66 C0 E_FIPS...,`.·dfÀ
000002F0 5D 13 D2 1A 83 E2 31 40 59 DD EA 39 E9 78 66 40 ].Ò.ƒâ1@YÝê9éxf@
00000300 7E F5 84 5A 90 D6 51 40 01 00 00 00 00 00 00 00 ~õ„Z.ÖQ@........
00000310 90 2C 60 02 B7 64 66 C0 F0 16 48 50 FC 0A 46 40 .,`.·dfÀð.HPü.F@
00000320 59 DD EA 39 E9 78 66 40 7E F5 84 5A 90 D6 51 40 YÝê9éxf@~õ„Z.ÖQ@
00000330 0E 00 00 00 00 00 00 00 73 FA 1D BE 16 27 5F C0 ........sú.¾.'_À