Распакуйте zip-файл внутри другого zip-файла с помощью SharpZipLib

Я пытаюсь распаковать zip-файл, который находится внутри другого zip-файла. Когда я пытаюсь получить FileStream второй почтовый индекс дает мне ошибку. Как я мог просматривать контент? Это мой код:

try
        {
            FileStream fs = File.OpenRead(location);
            ZipFile zipArchive = new ZipFile(fs);
            foreach (ZipEntry elementInsideZip in zipArchive)
            {
                String ZipArchiveName = elementInsideZip.Name;
                if (ZipArchiveName.Equals("MyZMLFile.xml"))
                {
                    // I NEED XML FILES
                    Stream zipStream = zipArchive.GetInputStream(elementInsideZip);
                    doc.Load(zipStream);
                    break;
                }
                // HERE!! I FOUND ZIP FILE
                else if (ZipArchiveName.Contains(".zip"))
                {
                    // I NEED XML FILES INSIDE THIS ZIP
                    string filePath2 = System.IO.Path.GetFullPath(ZipArchiveName);
                    ZipFile zipArchive2 = null;
                    FileStream fs2 = File.OpenRead(filePath2);// HERE I GET ERROR: Could not find a part of the path
                    zipArchive2 = new ZipFile(fs2);
                }
            }
        }

2 ответа

Решение

В этот момент имя zip-архива не является файлом на диске. Это просто файл внутри zip-архива, как и XML-файлы. Вы должны GetInputStream() для этого, как вы делаете для файлов xml, Stream zipStream = zipArchive.GetInputStream(elementInsideZip); Затем вы можете повторить метод, чтобы извлечь этот zip снова.

Сначала нужно извлечь zip-файл, а затем рекурсивно вызвать ту же функцию (поскольку этот zip-файл также может содержать zip-файл):

private static void ExtractAndLoadXml(string zipFilePath, XmlDocument doc)
{
    using(FileStream fs = File.OpenRead(zipFilePath))
    {
        ExtractAndLoadXml(fs, doc);
    }
}

private static void ExtractAndLoadXml(Stream fs, XmlDocument doc)
{
    ZipFile zipArchive = new ZipFile(fs);
    foreach (ZipEntry elementInsideZip in zipArchive)
    {
        String ZipArchiveName = elementInsideZip.Name;
        if (ZipArchiveName.Equals("MyZMLFile.xml"))
        {
            Stream zipStream = zipArchive.GetInputStream(elementInsideZip);
            doc.Load(zipStream);
            break;
        }
        else if (ZipArchiveName.Contains(".zip"))
        {
            Stream zipStream = zipArchive.GetInputStream(elementInsideZip);
            string zipFileExtractPath = Path.GetTempFileName();
            FileStream extractedZipFile = File.OpenWrite(zipFileExtractPath);
            zipStream.CopyTo(extractedZipFile);
            extractedZipFile.Flush();
            extractedZipFile.Close();
            try
            {
                ExtractAndLoadXml(zipFileExtractPath, doc);
            }
            finally
            {
                File.Delete(zipFileExtractPath);
            }
        }
    }
}

public static void Main(string[] args)
{
    string location = null;
    XmlDocument xmlDocument = new XmlDocument();
    ExtractAndLoadXml(location, xmlDocument);
}

Я не уверен, возможно ли это. Позволь мне объяснить:

Чтение ZIP-файла требует ввода-вывода файла произвольного доступа для чтения заголовков, таблицы файлов, таблицы каталогов и т. Д. Сжатый поток ZIP (файла) не предоставляет вам поток произвольного доступа, но обеспечивает последовательный поток - это как работают алгоритмы типа Deflate.

Чтобы загрузить zip-файл в zip-файл, сначала необходимо сохранить внутренний zip-файл. Для этого вы можете использовать временный файл или простой MemoryStream (если он не слишком большой). Это в основном предоставляет вам требование произвольного доступа, тем самым решая проблему.

Другие вопросы по тегам