如何通过VSIMEM实现FlatGeoBuf转GeoJSON(无磁盘写入)
FlatGeoBuf字节转GeoJSON(无磁盘写入)问题及解决
问题背景与初始尝试
我需要将从HTTP请求中读取的FlatGeoBuf字节数据转换为GeoJSON文件。已知可将.fgb文件存盘后用OGR打开,再通过已有函数导出GeoJSON,但希望完全避免磁盘写入。尝试使用GDAL的VSIMEM内存文件机制时遇到问题,初始代码如下:
def write_vsimem(mem_path: str, data: bytes) -> None: vsi_file = gdal.VSIFOpenL(mem_path, "w") size = len(data) try: gdal.VSIFWriteL(data, 1, size, vsi_file) if gdal.VSIFCloseL(vsi_file) != 0: raise RuntimeError( f"Failed to close VSIMEM file '{mem_path}': {gdal.GetLastErrorMsg()}" ) except Exception as e: raise RuntimeError(f"Error writing to VSIMEM file '{mem_path}': {e}") from e def convert_flatgeobuf_to_geojson(flatgeobuf_data: bytes, name: str) -> bytes: driver = ogr.GetDriverByName("FlatGeobuf") mem_path = f"/vsimem/{name}.fgb" fgb_data = driver.CreateDataSource(mem_path) if not fgb_data: raise RuntimeError(f"Failed to open FlatGeobuf file '{name}' with VSIMEM.") write_vsimem(mem_path, flatgeobuf_data) # Check if the layer exists if fgb_data.GetLayerCount() != 1: raise ValueError( f"Expected 1 layer in FlatGeobuf file '{name}', found {fgb_data.GetLayerCount()} layers." ) # Get the layer and extract geojson layer = fgb_data.GetLayer(0) return layer_to_geojson(layer=layer)
运行时日志显示write_vsimem执行正常:
Converting FlatGeoBuf of size: 5570849
Write VSIMEM: 5570816
但随后报错OGR数据源为空:
Failed to hydrate data: Expected 1 layer in FlatGeobuf file 'my_layer', found 0 layers.
需要明确:
- 无磁盘写入转换的目标是否可实现?
- 初始代码的错误点在哪里?
- 是否必须通过磁盘写入完成转换?
修正后的实现方案
根据提示,正确的实现方式是先将字节数据写入VSIMEM内存空间(无需调用CreateDataSource创建空数据源),再直接从内存路径打开数据源。修正后的代码如下:
def convert_flatgeobuf_to_geojson(flatgeobuf_data: bytes, name: str) -> bytes: mem_path = f"/vsimem/{name}.fgb" write_vsimem(mem_path, flatgeobuf_data) fgb_data = ogr.Open(mem_path) if not fgb_data: raise RuntimeError(f"Failed to open FlatGeobuf file '{name}' with VSIMEM.") # Check if the layer exists if fgb_data.GetLayerCount() != 1: raise ValueError( f"Expected 1 layer in FlatGeobuf file '{name}', found {fgb_data.GetLayerCount()} layers." ) # Get the layer and extract geojson layer = fgb_data.GetLayer(0) return layer_to_geojson(layer=layer, layer_name=name)
内容的提问来源于stack exchange,提问作者marting
相关产品推荐
相关产品推荐

