Найти строку в заархивированном файле без разархивирования файла - PullRequest
0 голосов
/ 08 февраля 2020

Есть ли способ поиска строки в файле (ах) в заархивированной папке БЕЗ разархивирования файлов?

В моей ситуации у меня более 1 миллиона файлов, заархивированных по месяцам года. Например, 2008_01, 2008_02 и др. c. Мне нужно извлечь / распаковать только файлы с указанными c серийными номерами внутри файлов.

Единственное, что я могу найти, - это разархивировать данные во временную папку для выполнения этого поиска, но это занимает у меня 45 -60 минут, чтобы распаковать данные вручную. Поэтому я предполагаю, что для выполнения этой задачи потребуется столько же времени, плюс у меня не так много свободного места.

Пожалуйста, помогите.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2020

Используя некоторые методы расширения, вы можете сканировать файлы Zip. Я не думаю, что вы можете получить что-либо, пытаясь сканировать один zip-файл параллельно, но вы, вероятно, могли бы сканировать несколько zip-файлов параллельно.

public static class ZipArchiveEntryExt {
    public static IEnumerable<string> GetLines(this ZipArchiveEntry e) {
        using (var stream = e.Open()) {
            using (var sr = new StreamReader(stream)) {
                string line;
                while ((line = sr.ReadLine()) != null)
                    yield return line;
            }
        }
    }
}

public static class ZipArchiveExt {
    public static IEnumerable<string> FilesContain(this ZipArchive arch, string target) {
        foreach (var entry in arch.Entries.Where(e => !e.FullName.EndsWith("/")))
            if (entry.GetLines().Any(line => line.Contains(target)))
                yield return entry.FullName;
    }

    public static void ExtractFilesContaining(this ZipArchive arch, string target, string extractPath) {
        if (!extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            extractPath += Path.DirectorySeparatorChar;

        foreach (var entry in arch.Entries.Where(e => !e.FullName.EndsWith("/")))
            if (entry.GetLines().Any(line => line.Contains(target)))
                entry.ExtractToFile(Path.Combine(extractPath, entry.Name));
    }
}

С их помощью вы можете искать zip-файл с помощью:

var arch = ZipFile.OpenRead(zipPath);

var targetString = "Copyright";
var filesToExtract = arch.FilesContain(targetString);

Вы также можете извлечь их по определенному пути (при условии отсутствия конфликтов имен файлов) с помощью:

var arch = ZipFile.OpenRead(zipPath);

var targetString = "Copyright";
arch.ExtractFilesContaining(targetString, @"C:\Temp");

Вы можете изменить ExtractFilesContaining, например, добавить год-месяц к имена файлов, чтобы избежать конфликтов.

0 голосов
/ 08 февраля 2020

К сожалению, нет способа сделать это. Формат zip поддерживает несжатый манифест, который показывает имена файлов и структуру каталогов, но содержимое самих файлов сжимается, и поэтому любая строка внутри файла не будет соответствовать вашему поиску, пока файл не будет распакован.

Такое же ограничение существует практически со всеми форматами сжатия файлов общего назначения (7zip, gzip, rar, et c.). По сути, вы освобождаете место на диске за счет циклов процессора.

...