Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
 Аватар для Orlov1
100 / 42 / 7
Регистрация: 03.02.2019
Сообщений: 655

Распаковка архивов

29.05.2025, 23:46. Показов 2632. Ответов 23

Студворк — интернет-сервис помощи студентам
Есть код, который распаковывает архивы, находящиеся в директории, используя стандартные средства Winrar и консольную команду. Подскажите как записать в коде обработку вложенных архивов, т.е если распаковали архив и в архиве еще один архив, то его распаковать с сохранением структуры каталогов.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
 
class ArchiveExtractor
{
    static void Main()
    {       
        string archivesPath = ("d:\\1\\");
 
        string outputPath = PrepareOutputDirectory();
                       
        string[] archiveFiles = Directory.GetFiles(archivesPath, "*.7z")
            .Concat(Directory.GetFiles(archivesPath, "*.zip"))
            .Concat(Directory.GetFiles(archivesPath, "*.rar"))
            .ToArray();
 
        foreach (string archivePath in archiveFiles)
        {
            ProcessArchive(archivePath, outputPath);
        }
                
        Console.ReadKey();
    }
 
    private static string PrepareOutputDirectory()
    {
        string outputPath = Path.Combine(Directory.GetCurrentDirectory(), "output");
        if (!Directory.Exists(outputPath))
            Directory.CreateDirectory(outputPath);
 
        return outputPath;
    }
    
    private static void ProcessArchive(string archivePath, string baseOutputPath)
    {
        string archiveName = Path.GetFileName(archivePath);
        Console.WriteLine($"Распаковка архива {archiveName}...");
 
        try
        {
           
            string archiveFolderName = Path.GetFileNameWithoutExtension(archivePath);
            string outputPath = Path.Combine(baseOutputPath, archiveFolderName);
 
            ExtractWithWinRAR(archivePath, outputPath);
 
            Console.WriteLine($"Распаковка архива {archiveName} завершена успешно.");
            
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ошибка при распаковке архива {archiveName}: {ex.Message}");
        }
    }
    
    private static void ExtractWithWinRAR(string archivePath, string outputPath)
    {
        string winRarPath = GetWinRarPath();
        if (winRarPath == null)
            throw new FileNotFoundException("WinRAR не найден!");
 
        Directory.CreateDirectory(outputPath);
                
        string args = $"x -ibck -y -r -o+ \"{archivePath}\" \"{outputPath}\"";
        using (Process process = new Process())
        
        {
            process.StartInfo = new ProcessStartInfo
            {
                FileName = winRarPath,
                Arguments = args,
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardError = true
            };
 
            process.Start();
            process.WaitForExit();
 
            if (process.ExitCode != 0)
                throw new Exception("Ошибка при распаковке архива.");
        }
 
    }
    private static string GetWinRarPath()
    {
        string[] possiblePaths =
        {
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WinRAR", "WinRAR.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "WinRAR", "WinRAR.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WinRAR", "Rar.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "WinRAR", "Rar.exe")
        };
 
        return possiblePaths.FirstOrDefault(File.Exists);
    }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.05.2025, 23:46
Ответы с готовыми решениями:

Распаковка архивов, в том числе и запароленных
Как распаковать запороленный архив WinRar или Zip, ну или хотя бы просто распаковать архив?

Распаковка rar-архивов
Перепрбывал много чего и в том числе сторонние библиотеки, вот код, надо расспаковать два архива....

Распаковка архивов в отдельные папки
имеется архив 123.rar, в нем находятся еще 3 архива 1.rar, 2.rar и 3.rar. Необходимо распаковать...

23
118 / 19 / 7
Регистрация: 27.05.2025
Сообщений: 72
30.05.2025, 00:55
Распаковывать архив в папку с именем архива, проверять там наличие архивов и повторять распаковку рекурсивно до тех пор пока архивы перестанут определяться.
0
Заблокирован
30.05.2025, 01:20
Создать метод ProcessDurectory и выносим в нее код касающийся поиска архивов и запуска их на распаковку.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    static void Main()
    {       
        string archivesPath = ("d:\\1\\");
        // запускаем обработку директории
        ProcessDirectory(archivesPath);
        Console.ReadKey();
    }
 
   private static void ProcessDirectory(string archivesPath){
      string outputPath = PrepareOutputDirectory();
                    
      string[] archiveFiles = Directory.GetFiles(archivesPath, "*.7z")
         .Concat(Directory.GetFiles(archivesPath, "*.zip"))
         .Concat(Directory.GetFiles(archivesPath, "*.rar"))
         .ToArray();
      
      foreach (string archivePath in archiveFiles)
      {
         ProcessArchive(archivePath, outputPath);
      }
   }
В ProcessArchive добавляем строчку обработки только что созданной директории после распаковки.
C#
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
        try
        {
           
            string archiveFolderName = Path.GetFileNameWithoutExtension(archivePath);
            string outputPath = Path.Combine(baseOutputPath, archiveFolderName);
 
            ExtractWithWinRAR(archivePath, outputPath);
 
            // рекурсивно обрабатываем распакованную директорию
            ProcessDirectory(outputPath);
            // ----
 
            Console.WriteLine($"Распаковка архива {archiveName} завершена успешно.");
            
        }
В теории. С минимальными правками. Не тестировал.

Всё это можно сделать и без рекурсии. Но правок понадобится намного больше.
1
 Аватар для qwerty.123
19 / 18 / 1
Регистрация: 25.05.2025
Сообщений: 39
30.05.2025, 14:40
C#
1
string outputPath = Path.Combine(Directory.GetCurrentDirectory(), "output");
Это можно записать компактней:
C#
1
string outputPath = $".{Path.DirectorySeparatorChar}output";
C#
1
2
if (!Directory.Exists(outputPath))
Directory.CreateDirectory(outputPath);
В данном случае нет смысла проверять каталог на существовании. Если каталога нет, то он будет создан. Если он уже существует, то ничего не произойдёт (т.е. никакого исключения не произойдёт).

А вообще, конечно же, в методе PrepareOutputDirectory() нет никакой необходимости.

C#
1
Console.WriteLine($"Ошибка при распаковке архива {archiveName}: {ex.Message}");
Привыкайте писать ошибки в правильный поток:

C#
1
Console.Error.WriteLine($"Ошибка при распаковке архива {archiveName}: {ex.Message}");
Кроме того, подход к решению, в целом, неправильный: а если на компьютере нет WinRar? Ведь далеко не у всех он есть: например, у меня его нет (использую 7Zip). А если приложение установлено portable в каталоге отличном от тех, в которых вы ищете exe-файл? А если это Linux или Mac? Не надо искать .exe-файлы. Вместо этого нужно подключить нужные NuGet-пакеты и использовать их. Лучше сразу привыкать писать кроссплатформенный код, если есть такая возможность (в данном случае она есть).

Возьмите за правило всегда первым делом валидировать параметры, полученные при вызове вашего метода. Например, проверяйте на то, что вам не передали пустые строки или null там, где они не должны появиться.

Если в вашем архиве есть несколько вложенных архивов, каждый из которых вы хотите распаковывать в отдельный подкаталог, то делайте это одновременно в параллельных потоках (у вас же не один одноядерный процессор на компьютере).
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,226
30.05.2025, 16:25
Цитата Сообщение от Orlov1 Посмотреть сообщение
Подскажите как записать в коде обработку вложенных архивов, т.е если распаковали архив и в архиве еще один архив, то его распаковать с сохранением структуры каталогов.
Можно как в DFS-е (поиск в глубину), обрабатывать архивы по одному на основе стека:
- Ложим все тарболы на стек, начинаем обрабатывать по одному
- После обработки каждого архива, проверяем его outputDir - создаем на его основе еще пачку задач на обработку, уже с новым baseOutputPath.

Вот так выглядит main после рефакторинга:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void Main()
    {       
        string archivesPath = ("d:\\1\\");
 
        var stack = new Stack<ProcessItem>();
        foreach (var archive in EnumerateArchives(archivesPath))
            stack.Push(new ProcessItem(archive));
        
        while (stack.Count > 0)
        {
            var item = stack.Pop();
            ProcessArchive(item);
 
            var outputDir = GetOutputDir(item);
            foreach (var archive in EnumerateArchives(outputDir))
                stack.Push(new ProcessItem(archive, outputDir));
        }
        
                
        Console.WriteLine("Process completed");
    }
Полный код

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System.Diagnostics;
 
class ArchiveExtractor
{
    private static readonly string BASE_OUTPUT_PATH = PrepareOutputDirectory();
    
    static void Main()
    {       
        string archivesPath = ("d:\\1\\");
 
        var stack = new Stack<ProcessItem>();
        foreach (var archieve in EnumerateArchieves(archivesPath))
            stack.Push(new ProcessItem(archieve));
        
        while (stack.Count > 0)
        {
            var item = stack.Pop();
            ProcessArchive(item);
 
            var outputDir = GetOutputDir(item);
            foreach (var tarball in EnumerateArchieves(outputDir))
                stack.Push(new ProcessItem(tarball, outputDir));
        }
        
                
        Console.WriteLine("Process completed");
    }
 
    private static string PrepareOutputDirectory()
    {
        string outputPath = Path.Combine(Directory.GetCurrentDirectory(), "output");
        if (!Directory.Exists(outputPath))
            Directory.CreateDirectory(outputPath);
 
        return outputPath;
    }
    
    private static void ProcessArchive(ProcessItem item)
    {
        string archiveName = Path.GetFileName(item.archievePath);
        Console.WriteLine($"Распаковка архива {archiveName}...");
 
        try
        {
            string outputPath = GetOutputDir(item);
            ExtractWithWinRAR(item.archievePath, outputPath);
 
            Console.WriteLine($"Распаковка архива {archiveName} завершена успешно.");
            
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ошибка при распаковке архива {archiveName}: {ex.Message}");
        }
    }
    
    private static void ExtractWithWinRAR(string archivePath, string outputPath)
    {
        string winRarPath = GetWinRarPath();
        if (winRarPath == null)
            throw new FileNotFoundException("WinRAR не найден!");
 
        Directory.CreateDirectory(outputPath);
                
        string args = $"x -ibck -y -r -o+ \"{archivePath}\" \"{outputPath}\"";
        using (Process process = new Process())
        
        {
            process.StartInfo = new ProcessStartInfo
            {
                FileName = winRarPath,
                Arguments = args,
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardError = true
            };
 
            process.Start();
            process.WaitForExit();
 
            if (process.ExitCode != 0)
                throw new Exception("Ошибка при распаковке архива.");
        }
 
    }
    private static string GetWinRarPath()
    {
        string[] possiblePaths =
        {
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WinRAR", "WinRAR.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "WinRAR", "WinRAR.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WinRAR", "Rar.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "WinRAR", "Rar.exe")
        };
 
        return possiblePaths.FirstOrDefault(File.Exists);
    }
 
    private static string GetOutputDir(ProcessItem item)
    {
        string archiveFolderName = Path.GetFileNameWithoutExtension(item.archievePath);
        return Path.Combine(item.baseOutputPath ?? BASE_OUTPUT_PATH, archiveFolderName);
    }
 
    private static IEnumerable<String> EnumerateArchives(String path)
    {
        return Directory.GetFiles(path, "*.7z")
            .Concat(Directory.GetFiles(path, "*.zip"))
            .Concat(Directory.GetFiles(path, "*.rar"))
    }
}
 
 
struct ProcessItem(string archievePath, string? baseOutputPath = null)
{
    internal String archievePath = archievePath; 
    
    internal String? baseOutputPath = baseOutputPath;
}


Добавлено через 28 секунд
Не тестировал, на лине сижу - тут WinRar-ов нету.

Добавлено через 15 минут
Немного еще рефакторинга (ProcessItem is immutable):
C#
1
2
3
4
5
6
readonly struct ProcessItem(string archievePath, string? baseOutputPath = null)
{
    internal readonly String archievePath = archievePath; 
    
    internal readonly String? baseOutputPath = baseOutputPath;
}
Добавлено через 3 минуты
Можно развить тему и передавать директорию через параметры приложения.

Добавлено через 8 минут
Orlov1, по поводу Directory.GetCurrentDirectory() - тут надо задать себе вопрос.
Задумка была действительно использовать текущую директорию или все-таки должна использоваться директория в которой лежит бинарь?
Потому что в общем случае это разные вещи.
2
Заблокирован
30.05.2025, 17:38
qwerty.123, #4 - план-"пятилетка" для начинающего

Добавлено через 1 минуту
p.s.:
Цитата Сообщение от qwerty.123 Посмотреть сообщение
Возьмите за правило всегда первым делом валидировать параметры
Я бы добавил: "в клиентском коде".
Не везде это нужно. Иначе получится "проверка проверкой погоняет".
0
 Аватар для qwerty.123
19 / 18 / 1
Регистрация: 25.05.2025
Сообщений: 39
30.05.2025, 17:50
Цитата Сообщение от SmallEvil
Не везде это нужно. Иначе получится "проверка проверкой погоняет".
Код метода не должен полагаться на то, что проверка параметров была выполнена в вызывающем этот метод коде. Во первых, такую проверку писать перед каждым вызовом метода будет утомительно. Во вторых, где-то могут сделать оЧепятку и проверка будет не совсем верной. В третьих, её вообще могут не делать.

Поэтому никогда не стоит полагаться на то, что полученные методом параметры уже были проверены извне. Ну и кроме того, всегда проще поправить логику проверки параметров в одном месте (в коде метода), чем везде, где этот метод вызывается (например в случае, если у метода была изменена сигнатура).

Соответственно, проверка параметров должна выполняться в одном месте - в коде самого метода (причём в самом начале). Например:

C#
1
2
3
4
5
static Task ExtractAsync(string zippedFileName, string targetDirectory, CancellationToken cancellationToken = default)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(zippedFileName, nameof(zippedFileName));
        ArgumentException.ThrowIfNullOrWhiteSpace(targetDirectory, nameof(targetDirectory));
...
Кстати, о необходимости проверки параметров в коде самого метода (если вы не пишете что-то низкоуровневое, системное, скрытое от внешнего использования) пишет в т.ч. и Беарне Стровструп (создатель языка C++) в своей книге "Практика программирования на C++".
0
Заблокирован
30.05.2025, 18:01
Цитата Сообщение от qwerty.123 Посмотреть сообщение
Код метода не должен полагаться на то, что проверка параметров была выполнена в вызывающем этот метод коде. Во первых, такую проверку писать перед каждым вызовом метода будет утомительно. Во вторых, где-то могут сделать оЧепятку и проверка будет не совсем верной. В третьих, её вообще могут не делать.
Это всё проблемы индейцев.
Есть контракты. Им нужно следовать. Всё просто.
Если контракт оглашает что данные должны быть строго такими-то, то это проблема вызывающего кода предоставить их.
Каким образом это будет осуществлено, это дело 100500-е.
имхо. наверное мы друг друга не поняли.

И ли это действительно Шарписты так пишут. 100500 проверок, а контракты зачем?
0
 Аватар для qwerty.123
19 / 18 / 1
Регистрация: 25.05.2025
Сообщений: 39
30.05.2025, 18:13
Цитата Сообщение от SmallEvil
И ли это действительно Шарписты так пишут. 100500 проверок, а контракты зачем?
Вот как раз чтобы не делать 100500 проверок, проверка параметров должна выполняться в коде метода, которому эти параметры переданы.

А ежели эти параметры передаются сквозным образом (от метода к методу), то ничего страшного в том, что каждый из них выполнит проверку.

Лучше проверить параметры несколько раз и выявить ошибку, чем не проверить их, выполнить часть бизнес-логики и потом вдруг обнаружить, что один из полученных параметров "кривой".

В нашей команде мы не пропускаем pull request, если в методе не выполняется проверка полученных параметров. Если вы работаете иначе - это ваше право.

Цитата Сообщение от SmallEvil
Есть контракты. Им нужно следовать. Всё просто.
Я не понимаю, о каких контрактах вы говорите. Под словом "контракт" я всегда подразумеваю программные интерфейсы (interface), перечисления (enums), абстрактные классы и делегаты. Т.е. абстрагирование от конкретных реализаций.
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,226
30.05.2025, 18:50
Цитата Сообщение от SmallEvil Посмотреть сообщение
Есть контракты.
А есть враждебный для публичных методов клиентский код, который может подсунуть все что угодно.
"Принцип самурая" никто не отменял.
0
Заблокирован
30.05.2025, 18:51

Не по теме:

Цитата Сообщение от qwerty.123 Посмотреть сообщение
Я не понимаю, о каких контрактах вы говорите.
На данный момент, я говорю немного абстрактно, о части более общего подхода(design by contract).
А именно : Контрактное программирование: предусловие
На англ. статья нагляднее
Design by contract

Но как бы это уже в оффтоп зашло.



Добавлено через 39 секунд
Цитата Сообщение от IamRain Посмотреть сообщение
А есть враждебный для публичных методов клиентский код, который может подсунуть все что угодно.
Это можно сделать в любом случае.
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,226
30.05.2025, 18:53
Цитата Сообщение от SmallEvil Посмотреть сообщение
а контракты зачем?
Вы что-то путаете. Как раз чтобы контракт соблюдался, нужно и валидировать параметры, контракт нарушен - делаем сэппуку.
0
30.05.2025, 18:54

Не по теме:

Цитата Сообщение от IamRain Посмотреть сообщение
Вы что-то путаете.
Шарписты это особый народец. )
Лады.
Ухожу в закат.

0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,226
30.05.2025, 18:56
Цитата Сообщение от SmallEvil Посмотреть сообщение
Это можно сделать в любом случае.
Что значит эта фраза?

Добавлено через 1 минуту

Не по теме:


Цитата Сообщение от SmallEvil Посмотреть сообщение
Шарписты это особый народец. )
У нас все формализовано, мало хаоса - это все идет на законодательном уровне (шучу, от Microsoft). А вы вносите хаос. :)

0
30.05.2025, 19:32

Не по теме:

Цитата Сообщение от IamRain Посмотреть сообщение
А вы вносите хаос. :)
Тут и без меня хорошо справляются)

0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,226
30.05.2025, 19:57
Orlov1, пожалуй, еще немного рефакторинга - сделал GetOutputDir экземплярным методом ProcessItem:

Main:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void Main()
    {       
        string archivesPath = ("d:\\1\\");
 
        var stack = new Stack<ProcessItem>();
        foreach (var archive in EnumerateArchives(archivesPath))
            stack.Push(new ProcessItem(archive));
        
        while (stack.Count > 0)
        {
            var item = stack.Pop();
            ProcessArchive(item);
 
            var outputDir = item.GetOutputDir();
            foreach (var archive in EnumerateArchives(outputDir))
                stack.Push(new ProcessItem(archive, outputDir));
        }
        
                
        Console.WriteLine("Process completed");
    }
Полный код

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System.Diagnostics;
 
class ArchiveExtractor
{
    internal static readonly string BASE_OUTPUT_PATH = PrepareOutputDirectory();
    
    static void Main()
    {       
        string archivesPath = ("d:\\1\\");
 
        var stack = new Stack<ProcessItem>();
        foreach (var archive in EnumerateArchives(archivesPath))
            stack.Push(new ProcessItem(archive));
        
        while (stack.Count > 0)
        {
            var item = stack.Pop();
            ProcessArchive(item);
 
            var outputDir = item.GetOutputDir();
            foreach (var archive in EnumerateArchives(outputDir))
                stack.Push(new ProcessItem(archive, outputDir));
        }
        
                
        Console.WriteLine("Process completed");
    }
 
    private static string PrepareOutputDirectory()
    {
        string outputPath = Path.Combine(Directory.GetCurrentDirectory(), "output");
        if (!Directory.Exists(outputPath))
            Directory.CreateDirectory(outputPath);
 
        return outputPath;
    }
    
    private static void ProcessArchive(ProcessItem item)
    {
        string archiveName = Path.GetFileName(item.archivePath);
        Console.WriteLine($"Распаковка архива {archiveName}...");
 
        try
        {
            ExtractWithWinRAR(item.archivePath, item.GetOutputDir());
            Console.WriteLine($"Распаковка архива {archiveName} завершена успешно.");
            
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ошибка при распаковке архива {archiveName}: {ex.Message}");
        }
    }
    
    private static void ExtractWithWinRAR(string archivePath, string outputPath)
    {
        string winRarPath = GetWinRarPath();
        if (winRarPath == null)
            throw new FileNotFoundException("WinRAR не найден!");
 
        Directory.CreateDirectory(outputPath);
                
        string args = $"x -ibck -y -r -o+ \"{archivePath}\" \"{outputPath}\"";
        using (Process process = new Process())
        
        {
            process.StartInfo = new ProcessStartInfo
            {
                FileName = winRarPath,
                Arguments = args,
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardError = true
            };
 
            process.Start();
            process.WaitForExit();
 
            if (process.ExitCode != 0)
                throw new Exception("Ошибка при распаковке архива.");
        }
 
    }
    private static string GetWinRarPath()
    {
        string[] possiblePaths =
        {
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WinRAR", "WinRAR.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "WinRAR", "WinRAR.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WinRAR", "Rar.exe"),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "WinRAR", "Rar.exe")
        };
 
        return possiblePaths.FirstOrDefault(File.Exists);
    }
    
    private static IEnumerable<String> EnumerateArchives(String path)
    {
        return Directory.GetFiles(path, "*.7z")
            .Concat(Directory.GetFiles(path, "*.zip"))
            .Concat(Directory.GetFiles(path, "*.rar"));
    }
}
 
 
readonly struct ProcessItem(string archivePath, string? baseOutputPath = null)
{
    internal readonly String archivePath = archivePath;
 
    private readonly String? baseOutputPath = baseOutputPath;
 
    internal string GetOutputDir() =>
        Path.Combine(baseOutputPath ?? ArchiveExtractor.BASE_OUTPUT_PATH,
            Path.GetFileNameWithoutExtension(archivePath));
}
0
30.05.2025, 21:15

Не по теме:

Цитата Сообщение от qwerty.123 Посмотреть сообщение
Возьмите за правило всегда первым делом валидировать параметры, полученные при вызове вашего метода.
Цитата Сообщение от qwerty.123 Посмотреть сообщение
Поэтому никогда не стоит полагаться на то, что полученные методом параметры уже были проверены извне.
Эти два слова стоит употреблять в крайне исключительных ситуациях, и хорошо обдумать нужны ли они там.
Я лишь написал, что не согласен именно в категоричности ваших суждений.

0
 Аватар для qwerty.123
19 / 18 / 1
Регистрация: 25.05.2025
Сообщений: 39
30.05.2025, 21:43
Цитата Сообщение от SmallEvil
Эти два слова стоит употреблять в крайне исключительных ситуациях, и хорошо обдумать нужны ли они там.
Я лишь написал, что не согласен именно в категоричности ваших суждений.
Я так же писал следующее:
(если вы не пишете что-то низкоуровневое, системное, скрытое от внешнего использования)
Поскольку на C# пишут не ядро операционной системы, то я сознательно употребил эти слова.

Тема превратилась в холивар. Я более не буду писать в ней.
0
Заблокирован
30.05.2025, 22:17
Цитата Сообщение от qwerty.123 Посмотреть сообщение
Тема превратилась в холивар.
Конечно, безумное однобокое видение, приводящее к диким тормозам, легко приводят к холиварам и к Юнити и играм на них.
С геймплеем и графикой как у ДОС игр но с требованием современных игровых ПК.
0
31.05.2025, 08:44

Не по теме:

Тема превратилась в холивар. Я более не буду писать в ней.
Можно попросить модераторов вынести дискусию в отдельную тему, раз зацепились.

По "холивару": пишем, когда имеет смысл.

вариант 1: передаваемый параметр задействуется где-то там, а перед ним куча кода, который не очень хочется запускать в пустую.

вариант 2: это метод либы, и желательно чтобы выше отлавливалось не NRE внутренностей, а более осознанное исключение. Тут больше вопрос удобства работы с кодом и его сопровождением: найти в логах "ArgumentException parameter fileName" гораздо приятней чем просто NullReferenceException line 17.

Лепить такие проверки на каждый чих действительно не очень. Как вариант можно воспользоваться фичей "nullable reference" (хотя по ней тоже ведутся споры), тем самым контракт будет более явный когда можно, а когда нельзя передавать null. В этом случае компилятор подскажет, где следует выполнить проверки, а где избыточны.

Подход "ничего не знаю, вызывающая сторона должна валидировать данные" тоже имеет смысл, особенно когда остро стоит вопрос перфоманса. Тем не менее если вы копнёте те же исходники C#, там очень много таких проверок.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
31.05.2025, 08:44
Помогаю со студенческими работами здесь

Распаковка архивов
Пишу программу на c#. Она у меня распознает документы ворд и записывает их в таблицу. Теперь нужно...

Запуск архивов по очереди
Здравствуйте бьюсь над следующей проблемой на форме есть progressBar1 который должен менять свое...

Склеивание архивов GZipStream - Неверный размер файла
Всем привет. Пишу архиватор, который делит исходный файл на фрагменты, их жмёт GZipStream, далее...

Параллельное создание zip архивов на WEB странице останавливается
Не веб-сайте есть страничка &quot;Создать архивы&quot;. Жму кнопку, создаются пустые архивы и начинается...

Подвисания при распаковке архивов из ресурсов
Приветствую! Разрабатываю свой WPF, в ресурсах лежит большое количество тяжеловесных zip архивов....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru