/
EvilBeaver
/
OneScript
Обзор
Документация
Войти
/
EvilBeaver
/
OneScript
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
v2.0.1
src/OneScript.StandardLibrary/Zip/ZipReader.cs
174 строки
7 KB
EvilBeaver
Адаптация под библиотеку DotNetZip.Original
29 июл 2025, 15:59
29 июл 2025, 15:59
f69ff53
Код
Авторство
О чём код?
/*---------------------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; using System.Text; using Ionic.Zip; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using System.IO; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; using OneScript.Types; namespace OneScript.StandardLibrary.Zip { /// <summary> /// Объект чтения ZIP файлов. /// </summary> [ContextClass("ЧтениеZipФайла", "ZipFileReader")] public class ZipReader : AutoContext<ZipReader>, IDisposable { ZipFile _zip; ZipFileEntriesCollection _entriesWrapper; public ZipReader() { } public ZipReader(IValue filenameOrStream, string password = null, FileNamesEncodingInZipFile encoding = FileNamesEncodingInZipFile.Auto) { Open(filenameOrStream, password, encoding); } private void CheckIfOpened() { if(_zip == null) throw new RuntimeException("Архив не открыт"); } /// <summary> /// Открывает архив для чтения. /// </summary> /// <param name="filenameOrStream">Имя ZIP файла или Поток, который требуется открыть для чтения.</param> /// <param name="password">Пароль к файлу, если он зашифрован.</param> /// <param name="encoding">Кодировка имен файлов в архиве.</param> [ContextMethod("Открыть","Open")] public void Open(IValue filenameOrStream, string password = null, FileNamesEncodingInZipFile encoding = FileNamesEncodingInZipFile.Auto) { // fuck non-russian encodings on non-ascii files DotNetZipEncoding.SetDefault(Encoding.GetEncoding(866)); if (filenameOrStream.SystemType == BasicTypes.String) { _zip = ZipFile.Read(filenameOrStream.ToString(), new ReadOptions { Encoding = ChooseEncoding(encoding) }); } else if (filenameOrStream is IStreamWrapper stream) { _zip = ZipFile.Read(stream.GetUnderlyingStream(), new ReadOptions { Encoding = ChooseEncoding(encoding) }); } else { throw RuntimeException.InvalidArgumentType(nameof(filenameOrStream)); } _zip.Password = password; } private Encoding ChooseEncoding(FileNamesEncodingInZipFile encoding) { if (encoding == FileNamesEncodingInZipFile.Auto || encoding == FileNamesEncodingInZipFile.OsEncodingWithUtf8) return null; return Encoding.UTF8; } /// <summary> /// Извлечение всех файлов из архива /// </summary> /// <param name="where">Строка. Каталог в который извлекаются файлы</param> /// <param name="restorePaths">РежимВосстановленияПутейФайловZIP</param> [ContextMethod("ИзвлечьВсе","ExtractAll")] public void ExtractAll(string where, ZipRestoreFilePathsMode restorePaths = default) { CheckIfOpened(); _zip.FlattenFoldersOnExtract = restorePaths == ZipRestoreFilePathsMode.DontRestore; _zip.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; _zip.ExtractAll(where); } /// <summary> /// Извлечение элемента из архива /// </summary> /// <param name="entry">ЭлементZipФайла. Извлекаемый элемент.</param> /// <param name="destination">Каталог, в который извлекается элемент.</param> /// <param name="restorePaths">РежимВосстановленияПутейФайлов</param> /// <param name="password">Пароль элемента (если отличается от пароля к архиву)</param> [ContextMethod("Извлечь", "Extract")] public void Extract(ZipFileEntryContext entry, string destination, ZipRestoreFilePathsMode restorePaths = default, string password = null) { CheckIfOpened(); if (entry == null) { // Передали Неопределено // TODO сделать более строгий маршалинг с учетом всех тыщ особенностей для строк и прочего throw RuntimeException.InvalidNthArgumentType(1); } var realEntry = entry.GetZipEntry(); _zip.FlattenFoldersOnExtract = restorePaths == ZipRestoreFilePathsMode.DontRestore; realEntry.Password = password; using (FileStream streamToExtract = new FileStream(Path.Combine(destination, entry.Name), FileMode.Create)) { realEntry.Extract(streamToExtract); } } /// <summary> /// Закрыть архив и освободить объект. /// </summary> [ContextMethod("Закрыть", "Close")] public void Close() { Dispose(); } /// <summary> /// Коллекция элементов архива. /// </summary> [ContextProperty("Элементы", "Elements")] public ZipFileEntriesCollection Elements { get { CheckIfOpened(); if (_entriesWrapper == null) _entriesWrapper = new ZipFileEntriesCollection(_zip.Entries); return _entriesWrapper; } } [ScriptConstructor(Name = "Формирование неинициализированного объекта")] public static ZipReader Construct() { return new ZipReader(); } [ScriptConstructor(Name = "На основании имени файла или потока")] public static ZipReader Constructor(IValue dataSource, string password = null) { var dataSourceRawValue = dataSource ?? ValueFactory.CreateInvalidValueMarker(); return new ZipReader(dataSourceRawValue, password); } public void Dispose() { _entriesWrapper = null; if (_zip != null) { _zip.Dispose(); _zip = null; } } } }