.NET组件读取压缩包中的内存数据电子表格XLSX文件和图片,不需要解压

.NET组件支持读取ZIP中某个目录下所有文件名,读取某个文件内容到变量吗?不需要写入硬盘? 比如把EXCEL ABC.XLSX格式数据和图片目录一起打包。 用NPOI等组件读取ZIP中的ABC.XLSX文件内存字节数据?

✅ 完全支持!.NET 原生支持内存中操作ZIP文件

.NET 提供了强大的 System.IO.Compression.ZipArchive 类来完全在内存中处理ZIP文件,无需写入硬盘。

🚀 核心实现方案

1. 读取ZIP中特定目录的所有文件名

cs 复制代码
using System.IO.Compression;

public List<string> GetFilesInZipDirectory(byte[] zipData, string targetDirectory)
{
    var fileNames = new List<string>();
    
    using (var memoryStream = new MemoryStream(zipData))
    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
    {
        // 确保目录格式正确(以/结尾)
        var searchPath = targetDirectory.TrimEnd('/') + "/";
        
        foreach (var entry in archive.Entries)
        {
            // 检查是否在目标目录中且不是目录本身
            if (!entry.FullName.EndsWith("/") && 
                entry.FullName.StartsWith(searchPath, StringComparison.OrdinalIgnoreCase))
            {
                fileNames.Add(entry.FullName);
            }
        }
    }
    
    return fileNames;
}

2. 读取ZIP中特定文件内容到内存变量

cs 复制代码
public byte[] ReadFileFromZip(byte[] zipData, string filePathInZip)
{
    using (var memoryStream = new MemoryStream(zipData))
    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
    {
        var entry = archive.GetEntry(filePathInZip);
        if (entry != null)
        {
            using (var entryStream = entry.Open())
            using (var resultStream = new MemoryStream())
            {
                entryStream.CopyTo(resultStream);
                return resultStream.ToArray();
            }
        }
    }
    return null;
}

3. 读取文本文件内容

cs 复制代码
public string ReadTextFileFromZip(byte[] zipData, string filePathInZip, Encoding encoding = null)
{
    encoding = encoding ?? Encoding.UTF8;
    
    using (var memoryStream = new MemoryStream(zipData))
    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
    {
        var entry = archive.GetEntry(filePathInZip);
        if (entry != null)
        {
            using (var entryStream = entry.Open())
            using (var reader = new StreamReader(entryStream, encoding))
            {
                return reader.ReadToEnd();
            }
        }
    }
    return null;
}

📦 完整示例:读取打包的Excel和图片

cs 复制代码
public class ZipExcelReader
{
    public void ProcessPackagedExcel(byte[] zipData)
    {
        using (var memoryStream = new MemoryStream(zipData))
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
        {
            // 1. 查找Excel文件
            var excelEntry = archive.Entries.FirstOrDefault(e => 
                e.Name.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase));
            
            if (excelEntry != null)
            {
                // 2. 读取Excel文件到内存字节数组
                byte[] excelData;
                using (var excelStream = excelEntry.Open())
                using (var ms = new MemoryStream())
                {
                    excelStream.CopyTo(ms);
                    excelData = ms.ToArray();
                }
                
                // 3. 使用NPOI读取Excel数据(完全在内存中)
                ProcessExcelWithNPOI(excelData);
            }
            
            // 4. 读取images目录下的所有图片
            var imageEntries = archive.Entries.Where(e => 
                e.FullName.StartsWith("images/", StringComparison.OrdinalIgnoreCase) &&
                !e.FullName.EndsWith("/"));
            
            foreach (var imageEntry in imageEntries)
            {
                byte[] imageData;
                using (var imageStream = imageEntry.Open())
                using (var ms = new MemoryStream())
                {
                    imageStream.CopyTo(ms);
                    imageData = ms.ToArray();
                }
                
                Console.WriteLine($"图片: {imageEntry.FullName}, 大小: {imageData.Length} bytes");
                // 处理图片数据...
            }
        }
    }
    
    private void ProcessExcelWithNPOI(byte[] excelData)
    {
        using (var memoryStream = new MemoryStream(excelData))
        {
            // 使用NPOI读取内存中的Excel数据
            var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook(memoryStream);
            var sheet = workbook.GetSheetAt(0);
            
            // 读取单元格数据
            for (int i = 0; i < sheet.LastRowNum; i++)
            {
                var row = sheet.GetRow(i);
                if (row != null)
                {
                    var cell = row.GetCell(0);
                    if (cell != null)
                    {
                        Console.WriteLine($"单元格[{i},0]: {cell.ToString()}");
                    }
                }
            }
        }
    }
}

🔧 实用工具类

cs 复制代码
public static class ZipMemoryHelper
{
    // 获取ZIP中所有文件的树形结构
    public static Dictionary<string, List<string>> GetZipStructure(byte[] zipData)
    {
        var structure = new Dictionary<string, List<string>>();
        
        using (var memoryStream = new MemoryStream(zipData))
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
        {
            foreach (var entry in archive.Entries)
            {
                if (entry.FullName.EndsWith("/")) continue; // 跳过目录条目
                
                var directory = Path.GetDirectoryName(entry.FullName)?.Replace("\\", "/");
                if (string.IsNullOrEmpty(directory)) directory = "/";
                
                if (!structure.ContainsKey(directory))
                {
                    structure[directory] = new List<string>();
                }
                
                structure[directory].Add(Path.GetFileName(entry.FullName));
            }
        }
        
        return structure;
    }
    
    // 检查ZIP中是否包含特定文件
    public static bool ZipContainsFile(byte[] zipData, string filePath)
    {
        using (var memoryStream = new MemoryStream(zipData))
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
        {
            return archive.GetEntry(filePath) != null;
        }
    }
    
    // 批量读取多个文件
    public static Dictionary<string, byte[]> ReadMultipleFiles(byte[] zipData, params string[] filePaths)
    {
        var results = new Dictionary<string, byte[]>();
        
        using (var memoryStream = new MemoryStream(zipData))
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
        {
            foreach (var filePath in filePaths)
            {
                var entry = archive.GetEntry(filePath);
                if (entry != null)
                {
                    using (var entryStream = entry.Open())
                    using (var ms = new MemoryStream())
                    {
                        entryStream.CopyTo(ms);
                        results[filePath] = ms.ToArray();
                    }
                }
            }
        }
        
        return results;
    }
}

🎯 使用示例

cs 复制代码
// 示例:从文件加载ZIP数据到内存
byte[] zipData = File.ReadAllBytes("package.zip");

// 1. 读取目录结构
var structure = ZipMemoryHelper.GetZipStructure(zipData);
foreach (var dir in structure)
{
    Console.WriteLine($"目录: {dir.Key}");
    foreach (var file in dir.Value)
    {
        Console.WriteLine($"  - {file}");
    }
}

// 2. 读取Excel文件并用NPOI处理
if (ZipMemoryHelper.ZipContainsFile(zipData, "data/workbook.xlsx"))
{
    byte[] excelData = ReadFileFromZip(zipData, "data/workbook.xlsx");
    
    // 使用NPOI处理内存中的Excel数据
    using (var ms = new MemoryStream(excelData))
    {
        var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook(ms);
        // ... NPOI操作
    }
}

// 3. 批量读取图片文件
var images = ZipMemoryHelper.ReadMultipleFiles(zipData, 
    "images/photo1.jpg", 
    "images/photo2.png", 
    "images/photo3.gif");

foreach (var image in images)
{
    Console.WriteLine($"{image.Key}: {image.Value.Length} bytes");
}

💡 关键优势

  1. 零磁盘IO:所有操作都在内存中进行

  2. 高性能:避免了文件系统开销

  3. 线程安全:每个操作使用独立的MemoryStream

  4. 资源管理:正确使用using语句确保资源释放

⚠️ 注意事项

  • 大文件需要注意内存使用量

  • ZipArchive是只读的,修改需要创建新的ZIP

  • 确保正确处理中文文件名编码

.NET 原生支持使得内存中处理ZIP文件变得非常简单高效!

相关推荐
轻松Ai享生活1 小时前
Linux Swap 详解 (1)
linux
重启的码农1 小时前
Windows虚拟显示器MttVDD源码分析 (6) 高级色彩与HDR管理
c++·windows·操作系统
東雪蓮☆1 小时前
深入理解 iptables:Linux 防火墙从入门到精通
linux·运维·网络
百锦再1 小时前
.NET + Vue 基于 WebSocket 的聊天室全面实现
vue.js·websocket·rabbitmq·.net·chat·message
CHEN5_022 小时前
【Java集合】List,Map,Set-详细讲解
java·windows·list
努力学习的小廉2 小时前
深入了解linux系统—— 线程互斥
linux·运维·服务器
zzz100662 小时前
CentOS 7 服务器初始化:从 0 到 1 的安全高效配置指南
服务器·安全·centos
会说话的吹风机2 小时前
五、VSCODE SSH连接linux服务器免密登录
服务器·vscode·ssh
JioJio~z3 小时前
PLC通讯中遇到的实际场景
运维·服务器·网络
青衫客363 小时前
负载均衡之带权重的随机负载均衡算法详解与实现
运维·服务器·负载均衡