You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP读取大型GeoJSON文件并提取法国滑雪山地数据写入新文件

处理大型GeoJSON文件:提取法国滑雪山地数据

需求说明

现有一个310MB的全球滑雪山地GeoJSON文件(world-ski-mtn.geojson),需要在PHP中实现以下操作:读取文件,筛选出属性中iso3166_1Alpha2为"FR"的法国区域记录,将筛选结果写入新文件。

解决方案

针对大体积文件,优先选择低内存占用的流式处理方案;若服务器内存充足,也可使用更简洁的数组过滤方案。

方案一:流式逐行处理(低内存占用,适合超大型文件)

通过文件指针逐行读取,仅在捕获到完整的Feature对象时进行解析和筛选,避免一次性加载整个文件到内存:

<?php
$inputFile = 'world-ski-mtn.geojson';
$outputFile = 'france-ski-mtn.geojson';

// 打开文件句柄
$inputHandle = fopen($inputFile, 'r');
$outputHandle = fopen($outputFile, 'w');

if (!$inputHandle || !$outputHandle) {
    die('文件打开失败');
}

// 写入GeoJSON头部
fwrite($outputHandle, '{"type": "FeatureCollection", "features":[');

$isFirstFeature = true;
$capturingFeature = false;
$currentFeatureContent = '';

while (($line = fgets($inputHandle)) !== false) {
    $trimmedLine = trim($line);
    
    // 检测Feature对象开始
    if (str_contains($trimmedLine, '"type": "Feature"')) {
        $capturingFeature = true;
        $currentFeatureContent = $line;
        continue;
    }
    
    // 收集Feature内容直到对象结束
    if ($capturingFeature) {
        $currentFeatureContent .= $line;
        if (str_ends_with($trimmedLine, '}') && !str_contains($trimmedLine, '{')) {
            $capturingFeature = false;
            // 解析当前Feature
            $feature = json_decode($currentFeatureContent, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                // 筛选法国区域数据
                if (isset($feature['properties']['location']['iso3166_1Alpha2']) 
                    && $feature['properties']['location']['iso3166_1Alpha2'] === 'FR') {
                    // 处理Feature间的逗号分隔
                    if (!$isFirstFeature) {
                        fwrite($outputHandle, ',');
                    }
                    fwrite($outputHandle, $currentFeatureContent);
                    $isFirstFeature = false;
                }
            }
            $currentFeatureContent = '';
        }
    }
}

// 写入GeoJSON尾部
fwrite($outputHandle, ']}');

// 关闭文件句柄
fclose($inputHandle);
fclose($outputHandle);

echo '筛选完成,结果已写入 ' . $outputFile;
?>

方案二:数组过滤(代码简洁,适合内存充足场景)

直接将整个文件加载为数组后过滤,代码更直观,但需要确保PHP的memory_limit足够(建议设置为512M或更高):

<?php
$inputFile = 'world-ski-mtn.geojson';
$outputFile = 'france-ski-mtn.geojson';

// 读取并解析GeoJSON文件
$geoJsonContent = file_get_contents($inputFile);
if ($geoJsonContent === false) {
    die('无法读取输入文件');
}

$geoJsonData = json_decode($geoJsonContent, true);
if (!isset($geoJsonData['features']) || !is_array($geoJsonData['features'])) {
    die('无效的GeoJSON格式');
}

// 筛选法国区域的Feature
$franceFeatures = array_filter($geoJsonData['features'], function($feature) {
    return isset($feature['properties']['location']['iso3166_1Alpha2']) 
        && $feature['properties']['location']['iso3166_1Alpha2'] === 'FR';
});

// 构造新的FeatureCollection并写入文件
$resultData = [
    'type' => 'FeatureCollection',
    'features' => array_values($franceFeatures)
];

if (file_put_contents($outputFile, json_encode($resultData, JSON_PRETTY_PRINT)) === false) {
    die('无法写入输出文件');
}

echo '筛选完成,结果已写入 ' . $outputFile;
?>

关键说明

  • 流式处理方案内存占用极低,适合处理几百MB甚至GB级的大型文件;
  • 数组过滤方案代码更简洁,但依赖服务器内存,310MB文件需确保内存配置足够;
  • 两种方案均保留原GeoJSON的数据结构,仅筛选符合条件的记录。

内容的提问来源于stack exchange,提问作者spreaderman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 15:09:12