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

PowerShell处理700MB JSON文件:如何高效列出所有键?

处理大体积JSON文件的高效方案

你的原代码之所以运行极慢,核心问题是**ConvertFrom-Json会将整个700MB的JSON数组一次性加载到内存并解析为PowerShell对象**,这会占用远超文件大小的内存,触发磁盘分页交换,导致速度骤降。下面是针对你的需求的高效解决方案:

一、高效提取所有唯一键

使用Newtonsoft.Json的流式读取器,无需加载整个文件到内存,逐对象提取键并自动去重:

# 先安装Newtonsoft.Json模块(首次运行需执行)
Install-Module -Name Newtonsoft.Json -Scope CurrentUser -Force

# 导入模块
Import-Module Newtonsoft.Json

$filePath = Convert-Path -LiteralPath names.json
$allKeys = [System.Collections.Generic.HashSet[string]]::new() # 自动去重的集合

# 创建流式读取器
$stream = [System.IO.File]::OpenText($filePath)
$reader = [Newtonsoft.Json.JsonTextReader]::new($stream)

try {
    # 跳过JSON数组的起始符号
    while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::StartArray) {}

    # 遍历数组中的每个对象
    while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::EndArray) {
        if ($reader.TokenType -eq [Newtonsoft.Json.JsonToken]::StartObject) {
            # 读取当前对象的所有键
            while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::EndObject) {
                if ($reader.TokenType -eq [Newtonsoft.Json.JsonToken]::PropertyName) {
                    [void]$allKeys.Add($reader.Value.ToString())
                }
            }
        }
    }
}
finally {
    # 确保资源释放
    $reader.Close()
    $stream.Close()
}

# 输出排序后的所有唯一键
$allKeys | Sort-Object

二、基于提取的键处理文件

1. 精简JSON(保留指定键)

假设你已确定需要保留的键列表$keepKeys,用流式方法过滤并输出新文件:

$keepKeys = @("word", "pos", "lang") # 替换为你要保留的键
$inputPath = Convert-Path -LiteralPath names.json
$outputPath = Convert-Path -LiteralPath trimmed_names.json

$streamIn = [System.IO.File]::OpenText($inputPath)
$reader = [Newtonsoft.Json.JsonTextReader]::new($streamIn)
$streamOut = [System.IO.File]::CreateText($outputPath)
$writer = [Newtonsoft.Json.JsonTextWriter]::new($streamOut)
$writer.Formatting = [Newtonsoft.Json.Formatting]::None # 关闭格式化进一步缩小体积

try {
    $writer.WriteStartArray() # 写入数组起始符号
    $firstObject = $true

    while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::EndArray) {
        if ($reader.TokenType -eq [Newtonsoft.Json.JsonToken]::StartObject) {
            if (-not $firstObject) { $writer.WriteRaw(',') }
            $firstObject = $false

            $writer.WriteStartObject()
            # 读取对象键值对,仅保留指定键
            while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::EndObject) {
                if ($reader.TokenType -eq [Newtonsoft.Json.JsonToken]::PropertyName) {
                    $key = $reader.Value.ToString()
                    if ($keepKeys -contains $key) {
                        $writer.WritePropertyName($key)
                        $reader.Read() # 定位到值的位置
                        $writer.WriteToken($reader) # 写入对应值
                    } else {
                        $reader.Skip() # 跳过不需要的键值对
                    }
                }
            }
            $writer.WriteEndObject()
        }
    }

    $writer.WriteEndArray() # 写入数组结束符号
}
finally {
    $reader.Close()
    $streamIn.Close()
    $writer.Close()
    $streamOut.Close()
}

2. 转换为包含所有键的CSV

利用提取到的所有键作为表头,流式读取每个对象的对应值,避免PowerShell默认ConvertTo-Csv丢失键的问题:

$allKeys = $allKeys | Sort-Object # 固定键顺序
$inputPath = Convert-Path -LiteralPath names.json
$outputPath = Convert-Path -LiteralPath output.csv

# 创建CSV写入器
$csvWriter = [System.IO.StreamWriter]::new($outputPath)
$csvWriter.WriteLine($allKeys -join ',') # 写入表头

$streamIn = [System.IO.File]::OpenText($inputPath)
$reader = [Newtonsoft.Json.JsonTextReader]::new($streamIn)

try {
    # 跳过数组起始符号
    while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::StartArray) {}

    while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::EndArray) {
        if ($reader.TokenType -eq [Newtonsoft.Json.JsonToken]::StartObject) {
            $objectValues = [ordered]@{}
            # 读取当前对象的所有键值对
            while ($reader.Read() -and $reader.TokenType -ne [Newtonsoft.Json.JsonToken]::EndObject) {
                if ($reader.TokenType -eq [Newtonsoft.Json.JsonToken]::PropertyName) {
                    $key = $reader.Value.ToString()
                    $reader.Read()
                    # 处理CSV格式,字符串用双引号包裹并转义内部引号
                    $value = if ($reader.Value -is [string]) {
                        '"' + $reader.Value.ToString().Replace('"', '""') + '"'
                    } else {
                        $reader.Value.ToString()
                    }
                    $objectValues[$key] = $value
                }
            }
            # 按表头顺序生成行数据,缺失的键填充空字符串
            $row = $allKeys | ForEach-Object { $objectValues[$_] ?? '' }
            $csvWriter.WriteLine($row -join ',')
        }
    }
}
finally {
    $reader.Close()
    $streamIn.Close()
    $csvWriter.Close()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 10:07:21