如何用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
相关产品推荐
相关产品推荐

