diff --git a/FileSplitter/FileSplitter.csproj b/FileSplitter/FileSplitter.csproj
index e052a83..2792840 100644
--- a/FileSplitter/FileSplitter.csproj
+++ b/FileSplitter/FileSplitter.csproj
@@ -7,6 +7,24 @@
enable
FileSplitter.Console
FileSplitter
+ FileSplitter
+
ANB Software File Splitter Console
+ 2023.04.09
+ Alexander Babaev
+ ANB Software File Splitter
+ Console App for ANB Software File Splitter. Split and join any file.
+ Alexander Babaev
+ https://git.babaev-an.ru/babaev-an/FileSplitter
+ https://git.babaev-an.ru/babaev-an/FileSplitter.git
+ ru
+
+
+
+
+
+
+
+
diff --git a/FileSplitter/Program.cs b/FileSplitter/Program.cs
index f83987b..fef5bdd 100644
--- a/FileSplitter/Program.cs
+++ b/FileSplitter/Program.cs
@@ -1,66 +1,128 @@
-//Приветственное сообщение
-Console.WriteLine("ANB Software Делитель файлов");
-Console.WriteLine("в. 2023.04.08");
+using System.Reflection;
-//Вывожу помощь
-Help();
+using anbs_cp.Classes;
-//Команда
-string command;
+using FileSplitter.Shared.Classes;
+using FileSplitter.Shared.Enums;
-//Начинаю цикл
-do
+string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? string.Empty;
+
+//Инициализирую список параметров
+ConsoleParamsParser consoleParser = new(Environment.GetCommandLineArgs());
+
+//Приветственное сообщение
+Console.WriteLine("********************************************************************************");
+Console.WriteLine($"\t{Localization.AppTitle}");
+Console.WriteLine($"\t{string.Format(Localization.AppVersion, assemblyVersion)}");
+Console.WriteLine(
+ $"\t{string.Format(Localization.AppCopyrights, DateTime.Now.Year == 2023 ? "2023" : $"2023 - {DateTime.Now.Year}")}");
+Console.WriteLine("********************************************************************************");
+
+//Прерываем, если нет параметров
+if (!consoleParser.HasParam("split") && !consoleParser.HasParam("join"))
{
- //Запрос команды
- Console.WriteLine("Введите команду:");
-
- //Считывание команды
- command = (Console.ReadLine() ?? "").ToLower();
-
- //Выбор действия
- switch (command)
- {
- ////Если команда "Шифровка"
- //case "crypt" or "c":
- // //Запускаю сценарий шифровки
- // await CryptAsync();
- // break;
- ////Если команда "Дешифровка"
- //case "delete" or "d":
- // //Запускаю сценарий дешифровки
- // await DecryptAsync();
- // break;
- ////Если команда "Установочные файлы"
- //case "ifiles" or "i":
- // //Запускаю сценарий создания установочных файлов
- // await CreateInstallFilesInfoAsync();
- // break;
- ////Если команда "Помощь"
- //case "help" or "h":
- // //Запускаю сценарий помощи
- // Help();
- // break;
- //Если что-то другое
- default:
- //Вывожу сообщение об ошибке, если команда не "Выход"
- if (command is not ("exit" or "e"))
- Console.WriteLine("Команда не опознана! Повторите попытку ещё раз, введите [h]elp для помощи или введите [e]xit для выхода...");
- break;
- }
-} while (command is not ("exit" or "e"));
-
-static void SplitFile(string path)
-{
-
+ Console.WriteLine(Localization.MessageNoParameters);
+ return;
}
-//Информация о работе с программой
-static void Help ()
+//Разделение файлов
+if (consoleParser.HasParam("split"))
+ FileSplit(consoleParser);
+
+//Соединение файлов
+if (consoleParser.HasParam("join"))
+ FileJoin(consoleParser);
+
+//Функция разделения файлов
+static void FileSplit (ConsoleParamsParser @params)
{
- //Публикую сообщение о работе с программой
- Console.WriteLine("Информация о работе с программой:\n\t" +
- "[c]rypt - шифровка архива\n\t" +
- "[d]ecrypt - дешифровка архива\n\t" +
- "[i]files - создание списка установочных файлов\n\t" +
- "[e]xit - Выход из программы\n\t[h]elp - Повторный вывод этого сообщения.");
+ //Проверяю наличие параметров
+ if (!@params.HasParam("-fn") || !@params.HasParam("-td") || !@params.HasParam("-ps"))
+ {
+ //- вывожу сообщение
+ Console.WriteLine(Localization.MessageNoParametersForSplit);
+
+ //- прерываю
+ return;
+ }
+
+ //Получаю параметры
+ //- имя исходного файла
+ string fileName = @params.GetValue("-fn") ?? string.Empty;
+ //- папка для сохранения разбиения
+ string targetDir = @params.GetValue("-td") ?? string.Empty;
+ //- размер части
+ long partSize = TypeConverter.StrToInt64(@params.GetValue("-ps") ?? string.Empty);
+ //- параметры
+ List options = new();
+
+ //Проверяю параметры разбиения
+ //- отключена ли проверка хэша
+ if (@params.HasParam("/NoCheckHash"))
+ options.Add(FileSplitOptions.fsoNoCheckHash);
+ //- нужно ли удалять исходный файл
+ if (@params.HasParam("/DeleteSource"))
+ options.Add(FileSplitOptions.fsoDeleteSourceFileAfterSplit);
+ //- нужно ли шифровать файл информации
+ if (@params.HasParam("/EncryptInfoFile"))
+ options.Add(FileSplitOptions.fsoEncryptInfoFile);
+
+ //Функция прогресса
+ #pragma warning disable CS8622
+ FileSplitterClass.OnProgress += OnProgress;
+ #pragma warning restore CS8622
+
+ //Выполняю разбиение
+ FileSplitterClass.SplitFile(fileName, targetDir, partSize, options.AsReadOnly());
+}
+
+//Функция объединения
+static void FileJoin (ConsoleParamsParser @params)
+{
+ //Проверяю наличие параметров
+ if (!@params.HasParam("-ifn") || !@params.HasParam("-tfn"))
+ {
+ //- вывожу сообщение
+ Console.WriteLine(Localization.MessageNoParametersForSplit);
+
+ //- прерываю
+ return;
+ }
+
+ //Получаю параметры
+ //- имя файла с информацией о разбиении
+ string infoFileName = @params.GetValue("-ifn") ?? string.Empty;
+ //- имя целевого файла
+ string targetFileName = @params.GetValue("-tfn") ?? string.Empty;
+ //- параметры
+ List options = new();
+
+ //Проверяю параметры разбиения
+ //- отключена ли проверка хэша
+ if (@params.HasParam("/NoCheckHash"))
+ options.Add(FileJoinOptions.fjoNoCheckHash);
+ //- нужно ли удалять исходные файлы
+ if (@params.HasParam("/DeleteSource"))
+ options.Add(FileJoinOptions.fjoDeleteSourceFilesAfterJoin);
+ //- нужно ли дешифровать файл информации
+ if (@params.HasParam("/DecryptInfoFile"))
+ options.Add(FileJoinOptions.fjoInfoFileIsEncrypted);
+ //- нужно ли отключить проверку версии файла информации
+ if (@params.HasParam("/IgnoreVersion"))
+ options.Add(FileJoinOptions.fjoIgnoreSupportedScriptVersion);
+
+ //Функция прогресса
+ #pragma warning disable CS8622
+ FileSplitterClass.OnProgress += OnProgress;
+ #pragma warning restore CS8622
+
+ //Выполняю объединение
+ FileSplitterClass.JoinFile(infoFileName, targetFileName, options.AsReadOnly());
+}
+
+//Функция вывода прогресса
+static void OnProgress (object sender, FileSplitterOnProgress args)
+{
+ //Вывод сообщения в консоль
+ Console.WriteLine(args.Message);
}
\ No newline at end of file
diff --git a/FileSplitterProj.sln.DotSettings b/FileSplitterProj.sln.DotSettings
new file mode 100644
index 0000000..a08159e
--- /dev/null
+++ b/FileSplitterProj.sln.DotSettings
@@ -0,0 +1,7 @@
+
+ True
+ True
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/FileSplitterShared/Classes/FileSplitInfo.cs b/FileSplitterShared/Classes/FileSplitInfo.cs
index 1a9d90b..d961601 100644
--- a/FileSplitterShared/Classes/FileSplitInfo.cs
+++ b/FileSplitterShared/Classes/FileSplitInfo.cs
@@ -5,20 +5,27 @@ namespace FileSplitter.Shared.Classes;
///
/// Информация о разбиении
///
-public class FileSplitInfo
+public sealed class FileSplitInfo
{
+ public FileSplitInfo()
+ {
+ SplitFiles = new();
+ TargetFile = new TargetFileInfo();
+ FileSplitterVersion = FileSplitterConstants.CurrentSplitterVersion;
+ }
+
///
/// Версия программы, необходимая для сборки файла
///
- public string? FileSplitterVersion { get; set; }
+ public string FileSplitterVersion { get; set; }
///
/// Информация о собираемом файле
///
- public ITargetFileInfo? TargetFile { get; set; }
+ public TargetFileInfo TargetFile { get; set; }
///
/// Информация о частях файла
///
- public List? SplitFiles { get; set; }
+ public List SplitFiles { get; set; }
}
\ No newline at end of file
diff --git a/FileSplitterShared/Classes/FileSplitterClass.cs b/FileSplitterShared/Classes/FileSplitterClass.cs
new file mode 100644
index 0000000..c0627b7
--- /dev/null
+++ b/FileSplitterShared/Classes/FileSplitterClass.cs
@@ -0,0 +1,346 @@
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Text;
+
+using anbs_cp.Classes;
+using anbs_cp.Classes.Encrypt;
+
+using FileSplitter.Shared.Enums;
+using FileSplitter.Shared.Interfaces;
+
+using Newtonsoft.Json;
+
+namespace FileSplitter.Shared.Classes;
+
+///
+/// Класс операций
+///
+public static class FileSplitterClass
+{
+ ///
+ /// Событие прогресса
+ ///
+ public static event EventHandler? OnProgress;
+
+ ///
+ /// Разделение файла на части
+ ///
+ /// Имя файла для разделения
+ /// Папка, в которую нужно сохранить файлы
+ /// Размер части в байтах
+ /// Параметры разбиения
+ public static void SplitFile (string fileName, string targetDir, long partSize, ReadOnlyCollection options)
+ {
+ //Задаю обработчик для распаковки
+ EventHandler? onProgressEvent = OnProgress;
+
+ //Инициализирующее сообщение
+ onProgressEvent?.Invoke(null,
+ new(0, 0,
+ string.Format(Localization.MessageStartSplit, fileName,
+ new FileSizeConverter(Localization.FileSizeStrings).Convert(partSize),
+ targetDir
+ )));
+
+ //Создаю результат
+ FileSplitInfo splitInfo = new()
+ {
+ FileSplitterVersion = FileSplitterConstants.CurrentSplitterVersion
+ };
+
+ //Если целевая папка не создана
+ if (!Directory.Exists(targetDir))
+ //- то создаём её
+ Directory.CreateDirectory(targetDir);
+
+ //Получаю размер текущего файла
+ long fileSize = FileExtension.FileSize(fileName);
+
+ //Получаю информацию о целевом файле
+ splitInfo.TargetFile = new()
+ {
+ FileName = Path.GetFileName(fileName),
+ FileSize = fileSize,
+ FileHash = new FileHash(fileName).Hash,
+ // ReSharper disable once PossibleLossOfFraction
+ SplitCount = (long)Math.Round(fileSize / (decimal)partSize, MidpointRounding.ToPositiveInfinity)
+ };
+
+ //Открываю файл
+ BinaryReader fileReader = new(File.Open(fileName, FileMode.Open));
+
+ //Разделяю файлы
+ for (int i = 0; i < splitInfo.TargetFile.SplitCount; i++)
+ {
+ //Сообщение прогресса
+ onProgressEvent?.Invoke(null,
+ new(i + 1, splitInfo.TargetFile.SplitCount,
+ string.Format(Localization.MessageSplitFilePart, i + 1, splitInfo.TargetFile.SplitCount)));
+
+ //Имя части
+ string partName = $"{Path.GetFileName(fileName)}.part{i + 1}.fsf";
+ //Полный путь к файлу части
+ string partFileName = $"{LikeDelphi.IncludeTrailingBackslash(targetDir)}{partName}";
+
+ //Смещение части от начала исходного файла
+ int startPos = (int)(i * partSize);
+
+ //Размер части
+ long bufferSize = fileSize - startPos > 0 ? partSize : partSize + (fileSize - startPos);
+
+ //Считываю значения
+ byte[] buffer = fileReader.ReadBytes((int)bufferSize);
+
+ //Записываю значение в файл
+ //- открываю файл
+ BinaryWriter fileWriter = new(File.Create(partFileName, (int)bufferSize));
+ //- записываю файл
+ fileWriter.Write(buffer);
+ //- закрываю файл
+ fileWriter.Close();
+
+ //Создаю информацию о части
+ SplitFile fileInfo = new()
+ {
+ Num = i + 1,
+ Offset = startPos,
+ Size = new FileInfo(partFileName).Length,
+ Hash = new FileHash(partFileName).Hash
+ };
+
+ //Добавляю в файл информации
+ splitInfo.SplitFiles.Add(fileInfo);
+ }
+
+ //Закрываю исходный файл
+ fileReader.Close();
+ //- и освобождаю память
+ fileReader.Dispose();
+
+ //Инициализирующее сообщение
+ onProgressEvent?.Invoke(null,
+ new(0, 0,
+ string.Format(Localization.MessageSplitComplete, fileName)));
+
+ //Проверка сумм
+ if (!options.Contains(FileSplitOptions.fsoNoCheckHash))
+ //- и если не прошли проверку
+ if (!CheckHash(targetDir, Path.GetFileName(fileName), splitInfo.SplitFiles))
+ //- то удаляем файлы разбиения
+ DeleteSplitFiles(Path.GetFileName(fileName), targetDir, splitInfo.TargetFile.SplitCount);
+
+ //Имя файла информации о разбиении
+ string reportFileName = $"{LikeDelphi.IncludeTrailingBackslash(targetDir)}{Path.GetFileName(fileName)}.fsi";
+
+ //Записываю информацию о разбиении
+ //- создаю файл
+ StreamWriter writer = new(reportFileName, Encoding.UTF8, new() { Access = FileAccess.Write, Mode = FileMode.Create });
+ //- создаю данные для записи файла
+ string data = options.Contains(FileSplitOptions.fsoEncryptInfoFile)
+ ? StringEncrypt.Encrypt(JsonConvert.SerializeObject(splitInfo))
+ : JsonConvert.SerializeObject(splitInfo);
+ //- записываю в файл
+ writer.WriteLine(data);
+ //- закрываю файл
+ writer.Close();
+ //- освобождаю память
+ writer.Dispose();
+
+ //Если в опциях активирована опция удаления исходного файла
+ if (options.Contains(FileSplitOptions.fsoDeleteSourceFileAfterSplit))
+ //- то удаляю его
+ File.Delete(fileName);
+ }
+
+ ///
+ /// Объединение разъединенного файла
+ ///
+ /// Имя файла с информацией о разделении
+ /// Целевой файл
+ /// Параметры объединения
+ public static void JoinFile (string infoFileName, string targetFileName, ReadOnlyCollection options)
+ {
+ //Задаю обработчик для распаковки
+ EventHandler? onProgressEvent = OnProgress;
+
+ //Инициализирующее сообщение
+ onProgressEvent?.Invoke(null,
+ new(0, 0,
+ string.Format(Localization.MessageStartJoin, infoFileName, targetFileName)));
+
+ //Открываю файл для чтения
+ StreamReader reader = new(infoFileName, Encoding.UTF8);
+
+ //Читаю строку
+ string tLine = reader.ReadLine() ?? "{}";
+
+ //Освобождаю reader
+ reader.Close();
+ reader.Dispose();
+
+ //Содержимое файла информации о разбиении
+ string jsonData = options.Contains(FileJoinOptions.fjoInfoFileIsEncrypted)
+ ? StringEncrypt.Decrypt(tLine)
+ : tLine;
+
+ //Создаю переменную для информации о разбиении
+ FileSplitInfo splitInfo = new();
+
+ try
+ {
+ //Получаю информацию о разбиении
+ splitInfo = JsonConvert.DeserializeObject(jsonData) ?? splitInfo;
+ }
+ catch (Exception)
+ {
+ onProgressEvent?.Invoke(null,
+ new(0, 0, Localization.MessageJoinUnknownFile));
+ Environment.Exit(2);
+ }
+
+ //Проверяю версию
+ if (!options.Contains(FileJoinOptions.fjoIgnoreSupportedScriptVersion) &&
+ !FileSplitterConstants.SupportSplitterVersion.Contains(splitInfo.FileSplitterVersion))
+ {
+ //Вывожу сообщение
+ onProgressEvent?.Invoke(null,
+ new(0, 0, string.Format(Localization.MessageJoinUnsupportedFile, splitInfo.FileSplitterVersion)));
+
+ //Прерываю
+ return;
+ }
+
+ //Получаю папку с разделёнными файлами
+ string sourceDir = LikeDelphi.IncludeTrailingBackslash(Path.GetDirectoryName(infoFileName) ?? "");
+
+ //Проверяю хэш
+ if (!options.Contains(FileJoinOptions.fjoNoCheckHash) && !CheckHash(sourceDir,
+ Path.GetFileName(splitInfo.TargetFile.FileName), splitInfo.SplitFiles))
+ {
+ //Вывожу сообщение
+ onProgressEvent?.Invoke(null, new(0, 0, Localization.MessageJoinHashError));
+
+ //Прерываю
+ return;
+ }
+
+ //Открываю файл
+ BinaryWriter fileWriter = new(File.Create(targetFileName, (int)splitInfo.TargetFile.FileSize));
+
+ //Объединяю файлы
+ for (int i = 1; i <= splitInfo.TargetFile.SplitCount; i++)
+ {
+ //Вывожу сообщение
+ onProgressEvent?.Invoke(null,
+ new(i, splitInfo.TargetFile.SplitCount,
+ string.Format(Localization.MessageJoinFilePart, i, splitInfo.TargetFile.SplitCount)));
+
+ //Имя файла части
+ string partFileName = $"{sourceDir}{Path.GetFileName(splitInfo.TargetFile.FileName)}.part{i}.fsf";
+
+ //Параметры части
+ ISplitFile partInfo = splitInfo.SplitFiles.FirstOrDefault(file => file.Num == i) ?? new SplitFile();
+
+ //Читаю часть
+ //- открываю файл для чтения
+ BinaryReader fileReader = new(File.Open(partFileName, FileMode.Open));
+ //- считываю содержимое
+ byte[] buffer = fileReader.ReadBytes((int)partInfo.Size);
+ //- закрываю файл
+ fileReader.Close();
+ //- освобождаю память
+ fileReader.Dispose();
+
+ //Записываю часть в общий файл
+ fileWriter.Write(buffer);
+ }
+
+ //Закрываю целевой файл
+ fileWriter.Close();
+ //Освобождаю память
+ fileWriter.Dispose();
+
+ //Вывожу сообщение
+ onProgressEvent?.Invoke(null, new(0, 0, Localization.MessageJoinComplete));
+
+ //Удаляю разделённые файлы
+ if (options.Contains(FileJoinOptions.fjoDeleteSourceFilesAfterJoin))
+ DeleteSplitFiles(splitInfo.TargetFile.FileName, sourceDir, splitInfo.TargetFile.SplitCount);
+ }
+
+ ///
+ /// Удаление разделённых файлов
+ ///
+ /// Исходное имя файла (без пути!)
+ /// Целевая директория
+ /// Число разбиения
+ private static void DeleteSplitFiles (string fileName, string targetDir, long splitCount)
+ {
+ //Перебираю части
+ for (int i = 1; i < splitCount; i++)
+ {
+ //Имя части
+ string partName = $"{fileName}.part{i}.fsf";
+ //Полный путь к файлу части
+ string partFileName = $"{LikeDelphi.IncludeTrailingBackslash(targetDir)}{partName}";
+
+ //Удаляю файл
+ File.Delete(partFileName);
+ }
+
+ //Имя файла информации о разбиении
+ string reportFileName = $"{LikeDelphi.IncludeTrailingBackslash(targetDir)}{Path.GetFileName(fileName)}.fsi";
+
+ //Удаляю файл информации
+ File.Delete(reportFileName);
+ }
+
+ ///
+ /// Проверяет соответствие хэша файлов
+ ///
+ /// Базовая папка с файлами
+ /// Базовое имя файлов
+ /// Список параметров файлов разбиения
+ /// Прошли ли файлы проверку
+ private static bool CheckHash (string baseDir, string baseName, List fileList)
+ {
+ //Задаю обработчик для распаковки
+ EventHandler? onProgressEvent = OnProgress;
+
+ //Инициализирующее сообщение
+ onProgressEvent?.Invoke(null,
+ new(0, 0,
+ Localization.MessageHashCheckStart));
+
+ //Перебираю все части
+ foreach (SplitFile file in fileList)
+ {
+ //Полный путь к файлу части
+ string partFileName = $"{LikeDelphi.IncludeTrailingBackslash(baseDir)}{baseName}.part{file.Num}.fsf";
+
+ //Получаю хэш
+ IStructuralEquatable fileHashEq = new FileHash(partFileName).Hash;
+
+ //Если не равен
+ if (!fileHashEq.Equals(file.Hash, StructuralComparisons.StructuralEqualityComparer))
+ {
+ //- то сообщаю
+ onProgressEvent?.Invoke(null,
+ new(0, 0,
+ string.Format(Localization.MessageHashCheckFail, partFileName)));
+
+ //- и прерываю
+ return false;
+ }
+ }
+
+ //Везде хэш был равен
+ //- выдаю сообщение
+ onProgressEvent?.Invoke(null,
+ new(0, 0,
+ Localization.MessageHashCheckComplete));
+
+ //- и возвращаю результат
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/FileSplitterShared/Classes/FileSplitterConstants.cs b/FileSplitterShared/Classes/FileSplitterConstants.cs
new file mode 100644
index 0000000..1192853
--- /dev/null
+++ b/FileSplitterShared/Classes/FileSplitterConstants.cs
@@ -0,0 +1,17 @@
+namespace FileSplitter.Shared.Classes;
+
+///
+/// Неизменяемые константы программы
+///
+public static class FileSplitterConstants
+{
+ ///
+ /// Текущая версия информационного файла
+ ///
+ public static string CurrentSplitterVersion = "20230409";
+
+ ///
+ /// Все поддерживаемые версии информационного файла
+ ///
+ public static string[] SupportSplitterVersion = { "20230409" };
+}
\ No newline at end of file
diff --git a/FileSplitterShared/Classes/FileSplitterOnProgress.cs b/FileSplitterShared/Classes/FileSplitterOnProgress.cs
new file mode 100644
index 0000000..7143248
--- /dev/null
+++ b/FileSplitterShared/Classes/FileSplitterOnProgress.cs
@@ -0,0 +1,35 @@
+namespace FileSplitter.Shared.Classes;
+
+///
+/// Параметры события OnProgress
+///
+public class FileSplitterOnProgress: EventArgs
+{
+ ///
+ /// Конструктор
+ ///
+ /// Текущий прогресс
+ /// Максимальные прогресс
+ /// Сообщение
+ public FileSplitterOnProgress (long current, long total, string message)
+ {
+ CurrentProgress = current;
+ MaxProgress = total;
+ Message = message;
+ }
+
+ ///
+ /// Текущий прогресс
+ ///
+ public long CurrentProgress { get; }
+
+ ///
+ /// Максимальные прогресс
+ ///
+ public long MaxProgress { get; }
+
+ ///
+ /// Сообщение
+ ///
+ public string Message { get; }
+}
\ No newline at end of file
diff --git a/FileSplitterShared/Classes/Localization.cs b/FileSplitterShared/Classes/Localization.cs
new file mode 100644
index 0000000..a3fde19
--- /dev/null
+++ b/FileSplitterShared/Classes/Localization.cs
@@ -0,0 +1,31 @@
+namespace FileSplitter.Shared.Classes;
+
+public static class Localization
+{
+ //Параметры приложения
+ public const string AppTitle = "ANB Software Делитель файлов";
+ public const string AppVersion = "Версия: {0}";
+ public const string AppCopyrights = "Авторские права (C) {0}, Александр Бабаев.";
+
+ //Сообщения
+ public const string MessageNoParameters =
+ "Нет параметров. Информацию о работе с программой смотрите в файле \"Help\\Russian\\Console.html\"";
+ public const string MessageNoParametersForSplit =
+ "Не заданы параметры разбиения. Информацию о работе с программой смотрите в файле \"Help\\Russian\\Console.html\"";
+ public const string MessageStartSplit = "Запущено разбиение файла {0} на части размером {1} и сохранением их в директории {2}.";
+ public const string MessageSplitFilePart = "Идёт обработка части {0} из {1}...";
+ public const string MessageSplitComplete = "Разбиение файла {0} завершено!";
+ public const string MessageHashCheckStart = "Начинаю проверку хэша разбиения";
+ public const string MessageHashCheckFail = "К сожалению, файл \"{0}\" не прошёл проверку хэша!";
+ public const string MessageHashCheckComplete = "Проверка хэша завершена!";
+ public const string MessageStartJoin = "Запущено объединение файлов, заданных файлом информации {0}, в файл {1}.";
+ public const string MessageJoinUnsupportedFile = "К сожалению, версия файла информации {0} не поддерживается!";
+ public const string MessageJoinUnknownFile = "Не могу прочитать файл информации! Возможно он зашифрован?";
+ public const string MessageJoinHashError = "К сожалению, разделённые файлы не прошли проверку. Возможно они повреждены?";
+ public const string MessageJoinFilePart = "Идёт обработка части {0} из {1}...";
+ public const string MessageJoinComplete = "Объединение файла {0} завершено!";
+
+
+ //Константы размеров
+ public static readonly string[] FileSizeStrings = { "байт", "Кб", "Мб", "Гб", "Тб" };
+}
\ No newline at end of file
diff --git a/FileSplitterShared/Classes/SplitFile.cs b/FileSplitterShared/Classes/SplitFile.cs
index fa68456..6d069e4 100644
--- a/FileSplitterShared/Classes/SplitFile.cs
+++ b/FileSplitterShared/Classes/SplitFile.cs
@@ -5,12 +5,12 @@ namespace FileSplitter.Shared.Classes;
///
/// Разделенный файл
///
-public class SplitFile: ISplitFile
+public sealed class SplitFile: ISplitFile
{
///
/// Порядок части
///
- public byte Num { get; set; }
+ public int Num { get; set; }
///
/// Размер части
diff --git a/FileSplitterShared/Classes/TargetFileInfo.cs b/FileSplitterShared/Classes/TargetFileInfo.cs
index 2ce6d66..829db58 100644
--- a/FileSplitterShared/Classes/TargetFileInfo.cs
+++ b/FileSplitterShared/Classes/TargetFileInfo.cs
@@ -5,12 +5,21 @@ namespace FileSplitter.Shared.Classes;
///
/// Информация о целевом файле
///
-public class TargetFileInfo: ITargetFileInfo
+public sealed class TargetFileInfo: ITargetFileInfo
{
+ ///
+ /// Конструктор
+ ///
+ internal TargetFileInfo()
+ {
+ FileName = string.Empty;
+ FileHash = new byte[]{};
+ }
+
///
/// Имя файла
///
- public string? FileName { get; set; }
+ public string FileName { get; set; }
///
/// Размер файла
@@ -20,10 +29,10 @@ public class TargetFileInfo: ITargetFileInfo
///
/// md5-сумма файла для проверки
///
- public byte[]? FileHash { get; set; }
+ public byte[] FileHash { get; set; }
///
/// Количество частей
///
- public byte SplitCount { get; set; }
+ public long SplitCount { get; set; }
}
\ No newline at end of file
diff --git a/FileSplitterShared/Enums/FileJoinOptions.cs b/FileSplitterShared/Enums/FileJoinOptions.cs
new file mode 100644
index 0000000..5c7a910
--- /dev/null
+++ b/FileSplitterShared/Enums/FileJoinOptions.cs
@@ -0,0 +1,27 @@
+namespace FileSplitter.Shared.Enums;
+
+///
+/// Опции объединения файла
+///
+public enum FileJoinOptions
+{
+ ///
+ /// Не проверять контрольную сумму перед началом объединения
+ ///
+ fjoNoCheckHash = 0,
+
+ ///
+ /// Json-Файл информации о разбиении зашифрован
+ ///
+ fjoInfoFileIsEncrypted = 1,
+
+ ///
+ /// Удалить исходные файлы после объединения
+ ///
+ fjoDeleteSourceFilesAfterJoin = 2,
+
+ ///
+ /// Игнорировать не поддерживаемую версию файла информации
+ ///
+ fjoIgnoreSupportedScriptVersion = 3
+}
\ No newline at end of file
diff --git a/FileSplitterShared/Enums/FileSplitOptions.cs b/FileSplitterShared/Enums/FileSplitOptions.cs
new file mode 100644
index 0000000..e2d95ae
--- /dev/null
+++ b/FileSplitterShared/Enums/FileSplitOptions.cs
@@ -0,0 +1,22 @@
+namespace FileSplitter.Shared.Enums;
+
+///
+/// Опции разделения файла
+///
+public enum FileSplitOptions
+{
+ ///
+ /// Не проверять контрольную сумму после создания всех частей
+ ///
+ fsoNoCheckHash = 0,
+
+ ///
+ /// Шифровать json-Файл информации о разбиении
+ ///
+ fsoEncryptInfoFile = 1,
+
+ ///
+ /// Удалить исходный файл после разбиения
+ ///
+ fsoDeleteSourceFileAfterSplit = 2
+}
\ No newline at end of file
diff --git a/FileSplitterShared/FileSplitterShared.csproj b/FileSplitterShared/FileSplitterShared.csproj
index de61e59..c96047f 100644
--- a/FileSplitterShared/FileSplitterShared.csproj
+++ b/FileSplitterShared/FileSplitterShared.csproj
@@ -8,4 +8,9 @@
FileSplitter.Shared
+
+
+
+
+
diff --git a/FileSplitterShared/Interfaces/ISplitFile.cs b/FileSplitterShared/Interfaces/ISplitFile.cs
index b59bc7e..ee5db6a 100644
--- a/FileSplitterShared/Interfaces/ISplitFile.cs
+++ b/FileSplitterShared/Interfaces/ISplitFile.cs
@@ -8,7 +8,7 @@ public interface ISplitFile
///
/// Порядок части
///
- public byte Num { get; set; }
+ public int Num { get; set; }
///
/// Размер части
diff --git a/FileSplitterShared/Interfaces/ITargetFileInfo.cs b/FileSplitterShared/Interfaces/ITargetFileInfo.cs
index 98ad5e7..bd25c81 100644
--- a/FileSplitterShared/Interfaces/ITargetFileInfo.cs
+++ b/FileSplitterShared/Interfaces/ITargetFileInfo.cs
@@ -8,7 +8,7 @@ public interface ITargetFileInfo
///
/// Имя файла
///
- public string? FileName { get; set; }
+ public string FileName { get; set; }
///
/// Размер файла
@@ -18,10 +18,10 @@ public interface ITargetFileInfo
///
/// md5-сумма файла для проверки
///
- public byte[]? FileHash { get; set; }
+ public byte[] FileHash { get; set; }
///
/// Количество частей
///
- public byte SplitCount { get; set; }
+ public long SplitCount { get; set; }
}
\ No newline at end of file
diff --git a/output/x32/FileSplitter.exe b/output/x32/FileSplitter.exe
new file mode 100644
index 0000000..be9bc54
Binary files /dev/null and b/output/x32/FileSplitter.exe differ
diff --git a/output/x32/sni.dll b/output/x32/sni.dll
new file mode 100644
index 0000000..5fc21ac
Binary files /dev/null and b/output/x32/sni.dll differ