.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文件变得非常简单高效!

相关推荐
一叶之秋14121 小时前
Linux基础IO
linux·运维·服务器
love530love1 小时前
升级到 ComfyUI Desktop v0.7.0 版本后启动日志报 KeyError: ‘tensorrt‘ 错误解决方案
开发语言·windows·python·pycharm·virtualenv·comfyui·comfyui desktop
longerxin20205 小时前
在 Linux 上使用 SCP 将文件传输到 Windows(已开启 SSH)
linux·运维·ssh
王正南8 小时前
kali-linux 虚拟机连接安卓模拟器
android·linux·运维·虚拟机连接模拟器·安卓模拟器,linux虚拟机
Web极客码8 小时前
如何在Ubuntu服务器上安装和配置BIND9
服务器·数据库·ubuntu
吳所畏惧8 小时前
Linux环境/麒麟V10SP3下离线安装Redis、修改默认密码并设置Redis开机自启动
linux·运维·服务器·redis·中间件·架构·ssh
yueguangni9 小时前
sysstat 版本 10.1.5 是 CentOS 7 的默认版本,默认情况下确实不显示 %wait 字段。需要升级到新版sysstat
linux·运维·centos
Davina_yu9 小时前
Windows 下升级 R 语言至最新版
开发语言·windows·r语言
西***63479 小时前
全兼容・高安全:KVM 一站式服务器远程监控与管理指南
服务器
翔云 OCR API10 小时前
发票查验接口详细接收参数说明-C#语言集成完整示例-API高效财税管理方案
开发语言·c#