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

如何用C#将含100GB JSON数据的3GB Gzip文件解压到本地?

使用C#解压超大Gzip文件(3GB压缩包→100GB JSON)

当然可以用C#完成这个操作,你遇到的8GB限制并非C#本身的硬性限制,大概率是旧代码的低效实现或环境配置问题。以下是针对大文件场景的优化方案:


一、优化基础解压代码(解决大文件限制)

你的原始代码核心逻辑没问题,但可以通过指定缓冲区大小和磁盘优化选项提升效率、消除潜在的大小限制:

public static void DecompressLargeGzip(FileInfo fileToDecompress)
{
    const int bufferSize = 81920; // 80KB缓冲区,可根据磁盘IO性能调整
    string newFileName = Path.ChangeExtension(fileToDecompress.FullName, null);
    
    // 用SequentialScan告诉系统这是顺序读写,优化磁盘缓存
    using (FileStream originalFileStream = fileToDecompress.OpenRead())
    using (FileStream decompressedFileStream = new FileStream(
        newFileName, 
        FileMode.Create, 
        FileAccess.Write, 
        FileShare.None, 
        bufferSize, 
        FileOptions.SequentialScan))
    using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
    {
        decompressionStream.CopyTo(decompressedFileStream, bufferSize);
        Console.WriteLine($"Decompressed: {fileToDecompress.Name}");
    }
}

关键优化点:

  • 用Path.ChangeExtension替代字符串截取,避免文件名格式错误
  • 手动指定缓冲区大小,比默认4KB缓冲区大幅提升大文件读写效率
  • 添加FileOptions.SequentialScan,触发系统磁盘顺序读写优化

二、边解压边反序列化+保存原始JSON

如果你需要同时完成「解压保存JSON文件」和「反序列化处理数据」,可以通过手动缓冲区读写实现双操作,避免重复解压:

public static void DecompressAndProcess(FileInfo fileToDecompress)
{
    const int bufferSize = 81920;
    string jsonFileName = Path.ChangeExtension(fileToDecompress.FullName, null);
    
    using (FileStream originalFileStream = fileToDecompress.OpenRead())
    using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
    using (FileStream jsonFileStream = new FileStream(
        jsonFileName, 
        FileMode.Create, 
        FileAccess.Write, 
        FileShare.None, 
        bufferSize, 
        FileOptions.SequentialScan))
    {
        byte[] buffer = new byte[bufferSize];
        int bytesRead;
        while ((bytesRead = decompressionStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            // 写入解压后的JSON文件
            jsonFileStream.Write(buffer, 0, bytesRead);
            
            // 流式处理JSON块(避免加载整个100GB文件到内存)
            ProcessJsonChunk(buffer, bytesRead);
        }
        
        Console.WriteLine($"Decompressed and processed: {fileToDecompress.Name}");
    }
}

// 流式JSON处理示例(适配超大JSON数组场景)
private static void ProcessJsonChunk(byte[] buffer, int bytesRead)
{
    using var stream = new MemoryStream(buffer, 0, bytesRead);
    using var reader = new Utf8JsonReader(stream);
    
    while (reader.Read())
    {
        // 识别并反序列化单个JSON对象
        if (reader.TokenType == JsonTokenType.StartObject)
        {
            var model = JsonSerializer.Deserialize<YourBusinessModel>(ref reader);
            // 这里添加你的业务逻辑处理
        }
    }
}

注意事项:

  • 必须使用流式反序列化(如Utf8JsonReader或Newtonsoft.Json的JsonTextReader),绝对不能一次性将整个100GB JSON加载到内存
  • 如果JSON是数组格式,推荐用JsonSerializer.DeserializeAsyncEnumerable实现更优雅的逐对象读取

三、异步版本(避免阻塞主线程)

如果在UI或服务环境中执行,建议用异步方法避免线程阻塞:

public static async Task DecompressLargeGzipAsync(FileInfo fileToDecompress)
{
    const int bufferSize = 81920;
    string newFileName = Path.ChangeExtension(fileToDecompress.FullName, null);
    
    using (FileStream originalFileStream = fileToDecompress.OpenRead())
    using (FileStream decompressedFileStream = new FileStream(
        newFileName, 
        FileMode.Create, 
        FileAccess.Write, 
        FileShare.None, 
        bufferSize, 
        FileOptions.SequentialScan | FileOptions.Asynchronous))
    using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
    {
        await decompressionStream.CopyToAsync(decompressedFileStream, bufferSize);
        Console.WriteLine($"Decompressed: {fileToDecompress.Name}");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:09:17