Что такое код zip_entry_name


Содержание

java.util.zip.ZipEntry.getName() Method Example

Description

The java.util.zip.ZipEntry.getName() method returns the name of the entry.

Declaration

Following is the declaration for java.util.zip.ZipEntry.getName() method.

Returns

the name of the entry.

Pre-requisite

Create a file Hello.txt in D:> test > directory with the following content.

Example

The following example shows the usage of java.util.zip.ZipEntry.getName() method.

Let us compile and run the above program, this will produce the following result −

Работа с zip-архивами в PHP

Уже долгие годы самым распространенным форматом сжатия данных, является формат ZIP. Данный формат широко используется в разработках под web. Поэтому многие языки для web-программирования имеют либо встроенные средства или возможности подключения необходимых библиотек для работы с zip-архивами.

Непосредственно в самом PHP функций для распаковки и создания zip-архивов нету. Хотя это зависит, от вариантов его сборки. Но они присутствуют в PHP расширении “php_zip”. И именно оно позволяет работать с архивными zip-файлами.

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

С распаковкой архивов при веб разработке, приходиться сталкиваться наиболее часто, нежели при разработке прикладного ПО. Особенно когда возникает необходимость в пакетной загрузке данных (документы, сертификаты и т.д.). Ведь даже диалоговое окно для открытия файла в браузере, не имеет возможности мульти выбора файлов. Конечно, можно воспользоваться каким-либо flash-загрузчиком, но во многих ситуациях это не подходит. А значит остается всего один вариант – архивация данных. Для работы по распаковке архива есть ряд функций встроенных в расширение php_zip:

Закрывает архивный zip-файл. Параметр zip обязан быть zip-архивом, открытым до этого функцией zip_open().

Закрывает вхождение директории, специфицированное параметром zip_entry . Параметр zip_entry обязан быть правильным вхождением директории, открытым функцией zip_entry_open().

int zip_entry_filesize (resource $zip_entry )

Возвращает фактический размер вхождения директории zip_entry. Параметр zip_entry обязан быть правильным вхождением директории, открытым функцией zip_read().

string zip_entry_name (resource $zip_entry )

Возвращает имя вхождения директории zip_entry. Параметр zip_entry обязан быть правильным вхождением директории, открытым функцией zip_read().

bool zip_entry_open (resource $zip , resource $zip_entry [, string $mode ])

Открывает вхождение директории в zip-файле для чтения. Параметр zip это правильный дескриптор ресурса, возвращённый функцией zip_open(). Параметр zip_entry это ресурс вхождения директории, возвращённый функцией zip_read(). Необязательный параметр mode может быть одним из режимов, специфицированных в документации для fopen().

Примечание: в настоящее время mode игнорируется и всегда имеет значение “rb”.Это из-за тог, что zip поддерживается в PHP с доступом только для чтения. Возвращает true при успехе, false при неудаче. В отличие от fopen() и других подобных функций, возвращаемое значение функции zip_entry_open() указывает только на результат операции и не нужно для чтения или закрытия вхождения директории.

string zip_entry_read (resource $zip_entry [, int $length ])

Читает до length байтов из открытого вхождения директории. Если параметр length не специфицирован, Функция zip_entry_read() пытается прочитать 1024 байта. Параметр zip_entry является правильным вхождением директории, возвращённым функцией zip_read(). Возвращает прочитанные данные, или false, если достигнут конец файла.

Примечание: параметр length должен быть несжатым размером, который вы хотите прочитать.

resource zip_open (string $filename )

Открывает новый zip-архив для чтения. Параметр filename это имя файла открываемого zip-архива. Возвращает дескриптор ресурса для дальнейшего использования в zip_read() и zip_close(), или возвращает false, если filename не существует.

resource zip_read (resource $zip )

Читает следующее вхождение в файле zip-архива. Параметр zip обязан быть zip-архивом, открытым ранее функцией zip_open(). Возвращает ресурс вхождения директории для дальнейшего использования с zip_entry_… () функциями.

int zip_entry_compressedsize(resource $zip_entry )

Параметр zip_entry обязан быть правильным вхождением директории, открытым функцией zip_read(). Возвращает сжатый размер вхождения директории zip_entry.

string zip_entry_compressionmethod (resource $zip_entry )

Параметр zip_entry обязан быть правильным вхождением директории, открытым функцией zip_read(). Возвращает метод сжатия для вхождения директории zip_entry.

Ниже приведен найденный и модифицированный мной исходный код функции для распаковки архива. Данная функция производит распаковку архива в корневой каталог. Поэтому если есть необходимость в создании директории для последующего расположения в ней распакованных файлов и каталогов, то ее требуется слегка изменить.

Выше был продемонстрирован классический пример распаковки архива. Обратите внимание на то, что указанный к архиву путь, должен быть абсолютным. Но тем не менее существует еще одна возможность, чтобы его распаковать. Для этого нужно прибегнуть к помощи методов класса ZipArchive. Этот класс находится все в том же расширении “php_zip”. Итак для того чтобы применить другой вариант распаковки, необходимо написать следующий код:

Для распаковки архива у данного класса используется только один метод:

bool extractTo (string $destination [, mixed $entries ])

Будущая директория местонахождения распакованного архива задается в параметре $destination . Параметр $entries содержит элементы для извлечения. Он является необязательным и может принимать как одно значение, так и массив значений.

Второй вариант выглядит намного красивее и компактнее, чем первый, не так ли? Поэтому я свой выбор остановил именно на нем. И напоследок протестируем оба варианта на скорость распаковки архива объемом в 205Mb:

Создание архива

Создание архива происходит сложнее, чем его распаковка. Если конечно требуется создать архив с одним файлом или одной директорией, то здесь все просто. А вот если упаковывать директории с неограниченным уровнем вложенности каталогов, то здесь уже придется немного подумать. Во-первых, необходим хороший рекурсивный алгоритм для обхода директорий. Во-вторых, нужно дополнительно хранить локальное имя файла/каталога. Итак, для создания архива нам понадобятся четыре метода класса ZipArchive:

    bool addEmptyDir (string $dirname )

Добавляет в архив пустую директорию. Параметр dirname должен содержать имя директории. Метод в случае успеха возвращает true или false в противном случае.

vo >$filename [, string $localname = NULL [, int $start = 0 [, int $length = 0 ]]])

Добавляет в архив файл, который находится по указанному в параметре filename пути. Параметр localname отвечает за имя файла в архиве. И если он указан, то параметр filename будет переопределен. Параметры start и length , зарезервированы для будущих целей. Данный метод так же в случае успеха возвращает true или false в случае ошибки.

vo >$filename [, int $flags ])

Данный метод необходим для открытия нового архива с целью: чтения, записи или создания. Параметр filename должен содержать имя архива. Необязательный параметр flags используется в качестве режима открытия файла (ZIPARCHIVE::OVERWRITE, ZIPARCHIVE::CREATE, ZIPARCHIVE::EXCL, ZIPARCHIVE::CHECKCONS). Метод возвращает true в случае успеха или код ошибки (см. предопределенные константы ошибок).

vo >Этот метод закрывает открытый или созданный архив и сохраняет изменения. Данный метод автоматически вызывается в конце сценария.

Ниже приведен исходный код созданного класса, позволяющего производить создание zip-архивов:

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

    bool ToZip (string $source , string $destination )

Создает zip-архив. В параметре source требуется указать путь к каталогу или файлу, который требуется запаковать. А в качестве параметра destination передается имя будущего архива. Метод возвращает true в случае успеха или false в случае возникновения ошибки.

Предопределенные константы режима работы

ZIPARCHIVE::CREATE (integer) Создавать архив, если он не существует.
ZIPARCHIVE::OVERWRITE (integer) Всегда создавать новый архив, этот режим перезаписывает файлы, если они существуют.
ZIPARCHIVE::EXCL (integer) Выводить ошибку, если архив существует.
ZIPARCHIVE::CHECKCONS (integer) Выполнять дополнительные проверки на структуру архива, и выдавать ошибку при неудаче.

Предопределенные константы флагов

ZIPARCHIVE::FL_NOCASE (integer) Игнорировать регистр символов в именах элементов архива.
ZIPARCHIVE::FL_NODIR (integer) Не учитывать пути директорий в архиве.
ZIPARCHIVE::FL_COMPRESSED (integer) Читать сжатые данные.
ZIPARCHIVE::FL_UNCHANGED (integer) Использовать исходные данные, игнорируя изменения.

Предопределенные константы методов сжатия

ZIPARCHIVE::CM_DEFAULT (integer) Выбрать лучший метод сжатия deflate или stored (без сжатия).
ZIPARCHIVE::CM_STORE (integer) Метод сжатия stored (без сжатия).
ZIPARCHIVE::CM_SHRINK (integer) Метод сжатия shrunk.
ZIPARCHIVE::CM_REDUCE_1 (integer) Метод сжатия reduced with factor 1.
ZIPARCHIVE::CM_REDUCE_2 (integer) Метод сжатия reduced with factor 2.
ZIPARCHIVE::CM_REDUCE_3 (integer) Метод сжатия reduced with factor 3.
ZIPARCHIVE::CM_REDUCE_4 (integer) Метод сжатия reduced with factor 4.
ZIPARCHIVE::CM_IMPLODE (integer) Метод сжатия imploded.
ZIPARCHIVE::CM_DEFLATE (integer) Метод сжатия deflated.
ZIPARCHIVE::CM_DEFLATE64 (integer) Метод сжатия deflate64.
ZIPARCHIVE::CM_PKWARE_IMPLODE (integer) Метод сжатия PKWARE imploding.
ZIPARCHIVE::CM_BZIP2 (integer) Метод сжатия алгоритмом BZIP2

Предопределенные константы ошибок

Zip entry Получение имени

Студия выдает имена из arc.Entries в виде кракозяба, вроде такого:
«—в® в*Є®Ґ ⥮аЁп ®в*®бЁвҐ«м*®бвЁ.fb2»
настоящее имя такое:
«Что такое теория относительности.fb2»

Как правильно декодировать?

14.05.2020, 19:31

Получение имени файла
Подскажите как получить имя файла находящегося скажим в папке My music cредствами C#??

получение имени по ip из dyndns
У меня динамический реальный айпи и пользуюсь сервисом dyndns.com. Hostname, который я там.

Получение имени окна
Админы тут баг в форуме я как то стер всю сваю тему.

Получение имени класса-наследника
Есть базовый класс, в нём виртуальный метод принимающий некий параметр, у класса много наследников.

Получение значения по имени свойства класса
Доброго времени суток. Мне необходимо реализовать, чтобы можно было получить значение свойства.

Zip File. Extract ToDirectory Метод

Определение

Извлекает все файлы в указанном ZIP-архиве в каталогу в файловой системе. Extracts all the files in the specified zip archive to a directory on the file system.

Перегрузки

Извлекает все файлы в указанном ZIP-архиве в каталогу в файловой системе. Extracts all the files in the specified zip archive to a directory on the file system.

Извлекает все файлы в указанном архиве в каталоге в файловой системе. Extracts all of the files in the specified archive to a directory on the file system.

Извлекает все файлы в указанном ZIP-архиве к каталог в файловой системе и использует указанную кодировку для имен записей. Extracts all the files in the specified zip archive to a directory on the file system and uses the specified character encoding for entry names.

Извлекает все файлы в указанном архиве в каталоге в файловой системе. Extracts all of the files in the specified archive to a directory on the file system.

ExtractToDirectory(String, String)

Извлекает все файлы в указанном ZIP-архиве в каталогу в файловой системе. Extracts all the files in the specified zip archive to a directory on the file system.

Параметры

Путь к архиву, который требуется извлечь. The path to the archive that is to be extracted.

Путь к каталогу, в котором следует поместить извлеченные файлы, заданный как относительный или абсолютный путь. The path to the directory in which to place the extracted files, specified as a relative or absolute path. Относительный путь интерпретируется относительно текущего рабочего каталога. A relative path is interpreted as relative to the current working directory.

Исключения

Параметр destinationDirectoryName или sourceArchiveFileName является Empty, содержит только пробелы или хотя бы один недопустимый символ. destinationDirectoryName or sourceArchiveFileName is Empty, contains only white space, or contains at least one invalid character.

Параметр destinationDirectoryName или sourceArchiveFileName имеет значение null . destinationDirectoryName or sourceArchiveFileName is null .

Указанная длина пути в destinationDirectoryName или sourceArchiveFileName превышает максимальную длину, определенную в системе. The specified path in destinationDirectoryName or sourceArchiveFileName exceeds the system-defined maximum length.

Указанный путь недопустим (например, он соответствует неподключенному диску). The specified path is invalid (for example, it is on an unmapped drive).

Каталог, заданный параметром destinationDirectoryName , уже существует. The directory specified by destinationDirectoryName already exists.

-или- -or- Имя записи в архиве имеет значение Empty, содержит только пробелы или содержит по крайней мере один недопустимый символ. The name of an entry in the archive is Empty, contains only white space, or contains at least one invalid character.

— или — -or- Извлечение записи архива создаст файл, который находится вне каталога, заданного destinationDirectoryName . Extracting an archive entry would create a file that is outs >destinationDirectoryName . (Например, это может произойти, если имя записи содержит методы доступа родительского каталога.) (For example, this might happen if the entry name contains parent directory accessors.) -или- -or- Запись архива, которую требуется извлечь, имеет то же имя, что и запись, которая уже была извлекается из того же архива. An archive entry to extract has the same name as an entry that has already been extracted from the same archive.

Вызывающий код не имеет необходимого разрешения на доступ к архиву или целевому каталогу. The caller does not have the required permission to access the archive or the destination directory.

destinationDirectoryName или sourceArchiveFileName содержит недопустимый формат. destinationDirectoryName or sourceArchiveFileName contains an invalid format.

Не удалось найти sourceArchiveFileName . sourceArchiveFileName was not found.

Архив, заданный параметром sourceArchiveFileName , не является допустимым ZIP-архивом. The archive specified by sourceArchiveFileName is not a valid zip archive.

-или- -or- Не удалось найти запись архива или она была повреждена. An archive entry was not found or was corrupt.

— или — -or- Запись архива была сжата с помощью неподдерживаемого метода сжатия. An archive entry was compressed by using a compression method that is not supported.

Примеры

В этом примере показано, как создать и извлечь ZIP-архив с помощью ZipFile класса. This example shows how to create and extract a zip archive by using the ZipFile class. Она сжимает содержимое папки в ZIP-архив и извлекает это содержимое в новую папку. It compresses the contents of a folder into a zip archive and extracts that content to a new folder. Чтобы использовать класс ZipFile, укажите в проекте ссылку на сборку System.IO.Compression.FileSystem . To use the ZipFile class, you must reference the System.IO.Compression.FileSystem assembly in your project.

Комментарии

Этот метод создает указанный каталог и все подкаталоги. This method creates the specified directory and all subdirectories. Каталог назначения не может уже существовать. The destination directory cannot already exist. Исключения, связанные с проверкой путей в destinationDirectoryName параметрах или sourceArchiveFileName , вызываются перед извлечением. Exceptions related to validating the paths in the destinationDirectoryName or sourceArchiveFileName parameters are thrown before extraction. В противном случае, если во время извлечения возникает ошибка, архив остается частично извлеченным. Otherwise, if an error occurs during extraction, the archive remains partially extracted. Каждый извлеченный файл имеет тот же относительный путь к каталогу, destinationDirectoryName который указан в качестве исходной записи в корневую папку архива. Each extracted file has the same relative path to the directory specified by destinationDirectoryName as its source entry has to the root of the archive.

ExtractToDirectory(String, String, Boolean)

Извлекает все файлы в указанном архиве в каталоге в файловой системе. Extracts all of the files in the specified archive to a directory on the file system.

Параметры

Путь в файловой системе к архиву, который требуется извлечь. The path on the file system to the archive that is to be extracted.

Путь к целевому каталогу в файловой системе. The path to the destination directory on the file system. Указанный каталог не должен существовать, но каталог, в котором он находится, должен существовать. The directory specified must not exist, but the directory that it is contained in must exist.

Значение true для перезаписи файлов; в противном случае — значение false . true to overwrite files; false otherwise.

Исключения

sourceArchiveFileName или destinationDirectoryName представляет собой строку нулевой длины, содержащую только пробелы или один или несколько недопустимых символов, заданных методом InvalidPathChars. sourceArchiveFileName or destinationDirectoryName is a zero-length string, contains only whitespace, or contains one or more invalid characters as defined by InvalidPathChars.

Параметр sourceArchiveFileName или destinationDirectoryName имеет значение null . sourceArchiveFileName or destinationDirectoryName is null .

sourceArchiveFileName или destinationDirectoryName указывает путь, имя файла или оба параметра, которые превышают установленное в системе максимальное значение. sourceArchiveFileName or destinationDirectoryName specifies a path, a file name, or both that exceed the system-defined maximum length.

Путь, указанный sourceArchiveFileName или destinationDirectoryName , является недопустимым (например, он ведет на несопоставленный диск). The path specified by sourceArchiveFileName or destinationDirectoryName is invalid (for example, it is on an unmapped drive).

Каталог, заданный параметром destinationDirectoryName , уже существует. The directory specified by destinationDirectoryName already exists.

Произошла ошибка ввода-вывода. An I/O error has occurred.

Имя ZipArchiveEntry имеет нулевую длину, содержит только пробелы или один или несколько недопустимых символов, заданных методом InvalidPathChars. The name of a ZipArchiveEntry is zero-length, contains only whitespace, or contains one or more invalid characters as defined by InvalidPathChars.

Извлечение ZipArchiveEntry может привести к назначению файла, находящегося за пределами целевого каталога (например, из-за наличия методов доступа к родительскому каталогу). Extracting a ZipArchiveEntry would result in a file destination that is outside the destination directory (for example, because of parent directory accessors).

ZipArchiveEntry имеет то же имя, что и уже извлеченная запись из того же архива. A ZipArchiveEntry has the same name as an already extracted entry from the same archive.

У вызывающего объекта отсутствует необходимое разрешение. The caller does not have the required permission.

Параметр sourceArchiveFileName или destinationDirectoryName имеет недопустимый формат. sourceArchiveFileName or destinationDirectoryName is in an invalid format.

Не удалось найти sourceArchiveFileName . sourceArchiveFileName was not found.

Архив, заданный параметром sourceArchiveFileName , не является допустимым ZipArchive. The archive specified by sourceArchiveFileName is not a valid ZipArchive.

ZipArchiveEntry поврежден или не может быть найден. A ZipArchiveEntry was not found or was corrupt.

ZipArchiveEntry сжат с помощью неподдерживаемого метода сжатия. A ZipArchiveEntry has been compressed using a compression method that is not supported.

Комментарии

Указанный каталог не должен существовать. The specified directory must not exist. Метод создает указанный каталог и все подкаталоги. The method creates the specified directory and all subdirectories.

Если при извлечении архива возникла ошибка, архив будет извлечен частично. If there is an error while extracting the archive, the archive will remain partially extracted.

Каждая запись будет извлечена таким образом, что извлеченный файл имеет тот же относительный путь к тому destinationDirectoryName , что и запись в архив. Each entry will be extracted such that the extracted file has the same relative path to the destinationDirectoryName as the entry has to the archive.

Путь может указывать сведения относительного или абсолютного пути. The path can specify relative or absolute path information. Относительный путь интерпретируется относительно текущего рабочего каталога. A relative path is interpreted as relative to the current working directory.

Если файл для архивации имеет неверное время последнего изменения, то будет использоваться первая дата и время, представленные в формате метки времени ZIP (полночь 1 января 1980). If a file to be archived has an invalid last modified time, the first date and time representable in the Zip timestamp format (midnight on January 1, 1980) will be used.

ExtractToDirectory(String, String, Encoding)

Извлекает все файлы в указанном ZIP-архиве к каталог в файловой системе и использует указанную кодировку для имен записей. Extracts all the files in the specified zip archive to a directory on the file system and uses the specified character encoding for entry names.

Параметры

Путь к архиву, который требуется извлечь. The path to the archive that is to be extracted.

Путь к каталогу, в котором следует поместить извлеченные файлы, заданный как относительный или абсолютный путь. The path to the directory in which to place the extracted files, specified as a relative or absolute path. Относительный путь интерпретируется относительно текущего рабочего каталога. A relative path is interpreted as relative to the current working directory.

Кодирование, используемое при чтении или записи имен записей в этом архиве. The encoding to use when reading or writing entry names in this archive. Задайте значение для этого параметра, только если кодирование требуется для взаимодействия с инструментами и библиотеками ZIP-архива, которые не поддерживают кодирование UTF-8 для имен записей. Specify a value for this parameter only when an encoding is required for interoperability with zip archive tools and libraries that do not support UTF-8 encoding for entry names.

Исключения

Параметр destinationDirectoryName или sourceArchiveFileName является Empty, содержит только пробелы или хотя бы один недопустимый символ. destinationDirectoryName or sourceArchiveFileName is Empty, contains only white space, or contains at least one invalid character.

-или- -or- entryNameEncoding установлено на кодировку Юникода, отличное от UTF-8. entryNameEncoding is set to a Unicode encoding other than UTF-8.

Значение параметра destinationDirectoryName или sourceArchiveFileName — null . destinationDirectoryName or sourceArchiveFileName is null .

Указанная длина пути в destinationDirectoryName или sourceArchiveFileName превышает максимальную длину, определенную в системе. The specified path in destinationDirectoryName or sourceArchiveFileName exceeds the system-defined maximum length.

Указанный путь недопустим (например, он соответствует неподключенному диску). The specified path is invalid (for example, it is on an unmapped drive).

Каталог, заданный параметром destinationDirectoryName , уже существует. The directory specified by destinationDirectoryName already exists.

— или — -or- Имя записи в архиве имеет значение Empty, содержит только пробелы или содержит по крайней мере один недопустимый символ. The name of an entry in the archive is Empty, contains only white space, or contains at least one invalid character.

— или — -or- Извлечение записи архива создаст файл, который находится вне каталога, заданного destinationDirectoryName . Extracting an archive entry would create a file that is outs >destinationDirectoryName . (Например, это может произойти, если имя записи содержит методы доступа родительского каталога.) (For example, this might happen if the entry name contains parent directory accessors.) — или — -or- Запись архива, которую требуется извлечь, имеет то же имя, что и запись, которая уже была извлекается из того же архива. An archive entry to extract has the same name as an entry that has already been extracted from the same archive.

Вызывающий код не имеет необходимого разрешения на доступ к архиву или целевому каталогу. The caller does not have the required permission to access the archive or the destination directory.

destinationDirectoryName или sourceArchiveFileName содержит недопустимый формат. destinationDirectoryName or sourceArchiveFileName contains an invalid format.

Не удалось найти sourceArchiveFileName . sourceArchiveFileName was not found.

Архив, заданный параметром sourceArchiveFileName , не является допустимым ZIP-архивом. The archive specified by sourceArchiveFileName is not a valid zip archive.

— или — -or- Не удалось найти запись архива или она была повреждена. An archive entry was not found or was corrupt.

-или- -or- Запись архива была сжата с помощью неподдерживаемого метода сжатия. An archive entry was compressed by using a compression method that is not supported.

Комментарии

Этот метод создает указанный каталог и все подкаталоги. This method creates the specified directory and all subdirectories. Каталог назначения не может уже существовать. The destination directory cannot already exist. Исключения, связанные с проверкой путей в destinationDirectoryName параметрах или sourceArchiveFileName , вызываются перед извлечением. Exceptions related to validating the paths in the destinationDirectoryName or sourceArchiveFileName parameters are thrown before extraction. В противном случае, если во время извлечения возникает ошибка, архив остается частично извлеченным. Otherwise, if an error occurs during extraction, the archive remains partially extracted. Каждый извлеченный файл имеет тот же относительный путь к каталогу, destinationDirectoryName который указан в качестве исходной записи в корневую папку архива. Each extracted file has the same relative path to the directory specified by destinationDirectoryName as its source entry has to the root of the archive.

Если entryNameEncoding для параметра задано значение, отличное null от, имена записей декодированы в соответствии со следующими правилами. If entryNameEncoding is set to a value other than null , entry names are decoded according to the following rules:

Для имен записей, в которых не задан флаг кодировки языка (в битовом флаге общего назначения локального заголовка файла), имена записей декодированы с использованием указанной кодировки. For entry names where the language encoding flag (in the general-purpose bit flag of the local file header) is not set, the entry names are decoded by using the specified encoding.

Для записей, в которых установлен флаг кодировки языка, имена записей декодированы с помощью UTF-8. For entries where the language encoding flag is set, the entry names are decoded by using UTF-8.

Если entryNameEncoding параметр имеет null значение, имена записей декодированы в соответствии со следующими правилами. If entryNameEncoding is set to null , entry names are decoded according to the following rules:

Для записей, в которых не задан флаг кодировки языка (в битовом флаге общего назначения локального заголовка файла), имена записей декодированы с использованием текущей системной кодовой страницы по умолчанию. For entries where the language encoding flag (in the general-purpose bit flag of the local file header) is not set, entry names are decoded by using the current system default code page.

Для записей, в которых установлен флаг кодировки языка, имена записей декодированы с помощью UTF-8. For entries where the language encoding flag is set, the entry names are decoded by using UTF-8.

ExtractToDirectory(String, String, Encoding, Boolean)

Извлекает все файлы в указанном архиве в каталоге в файловой системе. Extracts all of the files in the specified archive to a directory on the file system.

Параметры

Путь в файловой системе к архиву, который требуется извлечь. The path on the file system to the archive that is to be extracted.

Путь к целевому каталогу в файловой системе. The path to the destination directory on the file system. Указанный каталог не должен существовать, но каталог, в котором он находится, должен существовать. The directory specified must not exist, but the directory that it is contained in must exist.

Кодирование, используемое при чтении имен записей в этом ZipArchive. The encoding to use when reading entry names in this ZipArchive.

Значение true для перезаписи файлов; в противном случае — значение false . true to overwrite files; false otherwise.

Исключения

sourceArchiveFileName или destinationDirectoryName представляет собой строку нулевой длины, содержащую только пробелы или один или несколько недопустимых символов, заданных методом InvalidPathChars. sourceArchiveFileName or destinationDirectoryName is a zero-length string, contains only whitespace, or contains one or more invalid characters as defined by InvalidPathChars.

— или — -or- entryNameEncoding установлено на кодировку Юникода, отличное от UTF-8. entryNameEncoding is set to a Unicode encoding other than UTF-8.

Параметр sourceArchiveFileName или destinationDirectoryName имеет значение null . sourceArchiveFileName or destinationDirectoryName is null .

sourceArchiveFileName или destinationDirectoryName указывает путь, имя файла или оба параметра, которые превышают установленное в системе максимальное значение. sourceArchiveFileName or destinationDirectoryName specifies a path, a file name, or both that exceed the system-defined maximum length.

Путь, указанный sourceArchiveFileName или destinationDirectoryName , является недопустимым (например, он ведет на несопоставленный диск). The path specified by sourceArchiveFileName or destinationDirectoryName is invalid (for example, it is on an unmapped drive).

Каталог, заданный параметром destinationDirectoryName , уже существует. The directory specified by destinationDirectoryName already exists.

Произошла ошибка ввода-вывода. An I/O error has occurred.

Имя ZipArchiveEntry имеет нулевую длину, содержит только пробелы или один или несколько недопустимых символов, заданных методом InvalidPathChars. The name of a ZipArchiveEntry is zero-length, contains only whitespace, or contains one or more invalid characters as defined by InvalidPathChars.

Извлечение ZipArchiveEntry может привести к назначению файла, находящегося за пределами целевого каталога (например, из-за наличия методов доступа к родительскому каталогу). Extracting a ZipArchiveEntry would result in a file destination that is outside the destination directory (for example, because of parent directory accessors).

ZipArchiveEntry имеет то же имя, что и уже извлеченная запись из того же архива. A ZipArchiveEntry has the same name as an already extracted entry from the same archive.

У вызывающего объекта отсутствует необходимое разрешение. The caller does not have the required permission.

Параметр sourceArchiveFileName или destinationDirectoryName имеет недопустимый формат. sourceArchiveFileName or destinationDirectoryName is in an invalid format.

Не удалось найти sourceArchiveFileName . sourceArchiveFileName was not found.

Архив, заданный параметром sourceArchiveFileName , не является допустимым ZipArchive. The archive specified by sourceArchiveFileName is not a valid ZipArchive.

Не удалось найти запись архива или она была повреждена. An archive entry was not found or was corrupt.

Запись архива была сжата с использованием неподдерживаемого метода сжатия. An archive entry has been compressed using a compression method that is not supported.

Комментарии

Указанный каталог не должен существовать. The specified directory must not exist. Этот метод создаст указанный каталог и все подкаталоги. This method will create the specified directory and all subdirectories.

Если при извлечении архива возникла ошибка, архив будет извлечен частично. If there is an error while extracting the archive, the archive will remain partially extracted.

Каждая запись будет извлечена таким образом, что извлеченный файл имеет тот же относительный путь к тому destinationDirectoryName , что и запись в архив. Each entry will be extracted such that the extracted file has the same relative path to the destinationDirectoryName as the entry has to the archive.

Путь может указывать сведения относительного или абсолютного пути. The path can specify relative or absolute path information. Относительный путь интерпретируется относительно текущего рабочего каталога. A relative path is interpreted as relative to the current working directory.

Если файл для архивации имеет неверное время последнего изменения, то будет использоваться первая дата и время, представленные в формате метки времени ZIP (полночь 1 января 1980). If a file to be archived has an invalid last modified time, the first date and time representable in the Zip timestamp format (midnight on January 1, 1980) will be used.

Мой пример работы с Единым реестром запрещенных сайтов

Приветствую Хабравчане.
По долгу службы пришлось делать выгрузку с Реестра запрещенных сайтов, что меня лично никак не радовало. Для этого пришлось приобрести eToken ключик электронной подписи, иначе этот .zip файл размером 78кб (пока что) не получить. Хорошо что вместе с клиент банком шел неограниченный по времени КриптоПРО, но вот КриптоАрм так же пришлось приобретать отдельно, благо что стоит он не дорого (1200р. неограниченная по времени лицензия). Для разработки я использовал PHP в связке с MySQL. Реализация под катом.

Для начала я создал таблицу в БД:

Так же я использую две переменных из таблицы settings_list:

Потом я положил файл запроса и его отделенной подписи в один каталог с PHP сформированными в точности как в памятке для операторов связи, назвав их соответственно request.xml и request.xml.sig.

Далее по cron’у я запускаю следующий скрипт:

В итоге на выходе имеем таблицу с блокированными доменами и IP адресами. Теперь можно, например, создать черный список для Squid:

acl reg_blacklist dst «/etc/squid/squid.reg_blacklist»
http_access deny reg_blacklist

Или на Perl создать запрещающие правила для NetFilter:

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.

Correctly decoding zip entry file names — CP437, UTF-8 or?

November 2020

6.1k раз

Я недавно написал почтовый файл библиотеки ввода / вывода под названием ZipZap , но я борюсь с правильно перекодировки имен файлов ввода почтового индекса из произвольных архивных файлов.

D.1 формат ZIP исторически поддерживается только оригинальный PC набор символов кодировки IBM, которые обычно называют IBM Code Page 437 .

Г.2 Если вообще немного цель 11 снята с охраны, имя файла и комментарий должен соответствовать оригинальной кодировке ZIP символов. Если общее назначение бит 11 установлен, то имя файл и комментарий должны поддерживать стандарт Unicode, версию 4.1.0 или выше, используя форму кодировки символов, определенную спецификацией для хранения UTF-8 .

Это означает, что соответствующие файлы почтового индекса кодирования имен файлов, как CP437, если бит EFS не установлен, то в этом случае имена файлов UTF-8.

К сожалению, кажется , что много инструментов почтового индекса или не установлен бит EFS правильно (например , Mac CLI, GUI зип) или использовать какую — либо другую кодировку, как правило , в систему по умолчанию один на (например , WinZip?). Если вы знаете , как WinZip, 7-Zip, Info-Zip, PKZIP, Java JAR / Zip, .NET Zip, dotnetzip и т.д. имена файлов закодировать и что они устанавливают свою «версию , сделанное» полем, когда проносясь , скажите , пожалуйста , ,

В частности, Info-Zip пытается это когда разархивирования :

  • Файловая система = MS-DOS (0) => CP437
    • за исключением: версия = 2.5, 2.6, 4.0 => ISO 8859-1
  • Файловая система HPFS = (6) => CP437
  • Файловая система NTFS = (10) и версия = 5,0 => CP437
  • в противном случае, ISO 8859-1

Если я хочу , чтобы поддержать проверки или извлечения из произвольных архивных файлов и сделать разумную попытку именем файла кодирование без флага EFS, что я могу искать?

Работаем с ZIP-архивами средствами MQL5 без использования сторонних библиотек

Оглавление

Введение

Однажды автора данной статьи привлекла интересная особенность функции CryptDecode, а именно — возможность распаковывать переданный ей ZIP-массив. Этот модификатор был введен разработчиками торговой платформы MetaTrader 5 для того, чтобы можно было распаковывать ответ некоторых серверов, используя стандартную функцию WebRequest. Однако из-за некоторых особенностей формата ZIP-файла, использовать ее напрямую было невозможно.

Требовалась дополнительная аутентификация: для распаковки архива необходимо знать его хеш-сумму до упаковки: Adler-32, которой, естественно, не было. Однако, при обсуждении этой проблемы, разработчики пошли навстречу и перегрузили CryptDecode и CryptEncode, ее зеркального близнеца, специальным флагом, игнорирующим хеш Adler32 при распаковке переданных данных. Для неискушенных в техническом плане пользователей это нововведение можно объяснить просто: благодаря ему стала возможной полнофункциональная работа с ZIP-архивами. Эта статья подробно описывает формат ZIP-файла, особенности хранения данных в нем и предлагает для работы с архивом удобный объектно-ориентированный класс CZip.

Для чего это нужно

Сжатие данных — одна из важнейших технологий, особенно распространенная в среде Web. Благодаря сжатию экономятся ресурсы, необходимые для передачи, хранения и обработки информации. Сжатие данных используется практически во всех областях коммуникаций и проникло практически во все задачи, с которыми мы сталкиваемся при работе на компьютере.

Не стала исключением и финансовая сфера: гигабайты тиковой истории, потоки котировок, включая слепки стаканов (Level2-данные), немыслимо хранить в сыром, несжатом виде. Многие серверы, в том числе предоставляющие аналитическую информацию, интересную для торговли, также хранят данных в ZIP-архивах. Раньше не представлялось возможным получать эти данные автоматически, используя штатные средства MQL5. Теперь ситуация изменилась.

С помощью функции WebRequest можно скачать ZIP-архив и на лету распаковать его данные прямо в оперативную память компьютера. Все эти возможности важны и обязательно будут востребованы многими трейдерами. Сжатие данных можно использовать даже для экономии оперативной памяти компьютера. О том, как это делается, посвящен раздел 3.2 данной статьи. Наконец, умение работать с ZIP-архивами открывает доступ к формированию документов типа Microsoft Office по стандарту Office Open XML, что, в свою очередь, сделает возможным создание простых файлов Excel или Word прямо из MQL5, также без использования сторонних DLL библиотек.

Как видно, применение ZIP-архивирования обширно, и класс, создаваемый нами, сослужит хорошую службу всем пользователям MetaTrader.

В первой главе данной статьи мы подробно опишем собственно формат ZIP-файла и поймем, из каких блоков данных он состоит. Данная глава будет интересна не только тем, кто изучает MQL, она также послужит хорошим образовательным материалом и тем, кто занимается изучением вопросов, связанных с архивированием и хранением данных. Вторая глава будет посвящена классам CZip, CZipFile и CZipDirectory — эти классы являются основными объектно-ориентированными элементами для работы с архивом. Третья глава описывает практические примеры, связанные с использованием архивирования. Четвертая глава является документацией к предлагаемым классам.

Итак, приступим к изучению этого самого распространенного типа архивирования.

Глава 1. Формат ZIP-файла и способ хранения данных в нем


1.1. Структура ZIP-файла

Формат ZIP был создан Филом Кацом в 1989 году и впервые был реализован в программе PKZIP для MS-DOS, выпущенной компанией PKWARE, основателем которой являлся Кац. Этот формат архива наиболее часто использует алгоритм сжатия данных DEFLATE. Наиболее распространенными программами для работы с этим форматом в среде Windows являются WinZip и WinRAR.

Важно понимать, что формат ZIP-архива развивался со временем и имеет несколько версий. В создании класса для работы с ZIP-архивом, мы будем опираться на официальную спецификацию формата версии 6.3.4, размещенную на сайте компании PKWARE по адресу: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT. Это последняя спецификация формата, датируемая 1 октября 2014 года. Сама спецификация формата достаточно обширна и включает описания множества нюансов.

В данной статье мы будем исходить из принципа наименьших усилий и создадим инструмент, который будет использовать лишь самые необходимые данные для успешной распаковки файлов и создания новых архивов. Это значит, что в определенной мере работа с ZIP-файлами будет ограничена — совместимость форматов не гарантируется, а значит, и не приходится говорить о полной «всеядности» архивов. Вполне возможно, что некоторые ZIP-архивы, созданные сторонними средствами, не смогут быть распакованы с помощью предложенного инструмента.

Каждый ZIP-архив — это бинарный файл, содержащий упорядоченную последовательность байтов. С другой стороны, в ZIP-архиве каждый файл имеет имя, атрибуты (например время модификации файла) и другие свойства, которые мы привыкли видеть в файловой системе любой операционной системы. Поэтому, помимо запакованных данных, каждый ZIP-архив хранит имя запакованного файла, его атрибуты и другую служебную информацию. Эта служебная информация располагается в строго определенном порядке и имеет регулярную структуру. Например, если в архиве содержатся два файла (File#1 и File#2), то архив будет иметь следующую схему:

Рис. 1. Схематичное представление ZIP-архива, содержащего два файла: File#1 и File#2

Позже мы разберем подробно каждый блок данной схемы, а сейчас дадим краткое описание этих блоков:

  • Local File Header — этот блок данных содержит основную информацию о запакованном файле: размер файла до и после упаковки, время модификации файла, контрольную сумму CRC-32 и локальный указатель на имя файла. Кроме того, этот блок содержит версию архиватора, необходимую для распаковки файла.
  • File Name последовательность байтов произвольной длины, образующая имя запакованного файла. При этом длина имени файла не должен превышать 65 536 символов.
  • File Data упакованное содержимое файла в виде байт-массива произвольной длины. Если файл пустой или представляет из себя каталог, то этот массив не используется, и сразу за именем файла или директории идет заголовок Local File Header, описывающий следующий файл.
  • Central Directory содержит расширенное представление данных в Local File Header. Помимо данных, содержащихся в Local File Header, содержит атрибуты файла, локальную ссылку на структуру Local File Header и некоторую другую, в большинстве случаев неиспользуемую информацию.
  • End of central directory record — эта структура представлена в каждом архиве единственным экземпляром и записывается в самый конец архива. Наиболее интересные данные, которые она содержит, это количество записей в архиве (или количество файлов и каталогов) и локальные ссылки на начало блока Central Directory.

Каждый блок данной схемы можно представить либо в виде регулярной структуры, либо в виде байт-массива произвольной длины. Каждую из структур, в свою очередь, можно описать с помощью одноименной конструкции программирования в MQL — структуры.

Структура всегда занимает строго определенное количество байтов, поэтому она не может содержать внутри себя массивы произвольной длины и строки. Однако она может содержать указатели на эти объекты. Именно поэтому названия файлов в архиве вынесены за пределы структуры, благодаря чему они могут иметь произвольную длину. То же относится к упакованным данным файлов — их размер является произвольным, поэтому и они содержатся за пределами структур. Таким образом, можно сказать, что ZIP-архив представляет из себя последовательность структур, строк и упакованных данных.

Формат ZIP-файла, помимо представленного выше, описывает дополнительную структуру, так называемый Data Descriptor. Эта структура используется только в том случае, если по каким-то причинам не удалось сформировать структуру Local File Header, и часть данных, необходимая для Local File Header, стала доступна уже после сжатия данных. На практике это очень экзотическая ситуация, поэтому данная структура практически никогда не используется, и в нашем классе для работы с архивами этот блок данных не поддерживается.

Обратите внимание, что согласно формату ZIP-архива каждый файл сжимается независимо от остальных. С одной стороны, это позволяет локализовать возникновение ошибок: «битый» архив можно восстановить, удалив файл с неправильным содержимым и оставив все остальное содержимое архива без изменений. С другой стороны, при сжатии каждого файла отдельно снижается эффективность сжатия, в особенности если каждый из файлов занимает мало места.

1.2. Изучаем ZIP-файл в шестнадцатеричном редакторе

Теперь, вооружившись самыми необходимыми знаниями, мы можем посмотреть, что находится внутри типичного ZIP-архива. Для этого воспользуемся одним из шестнадцатиричных редакторов, WinHex. Если по каким-то причинам WinHex’а у вас нет, вы можете воспользоваться любым другим шестнадцатиричным редактором. Ведь мы помним, что любой архив — это бинарный файл, который можно открыть как простую последовательность байтов. Для эксперимента создадим простой ZIP-архив, содержащий внутри себя один-единственный текстовый файл с фразой «HelloWorld!» («Привет Мир!»):

Рис. 2. Создание текстового файла в блокноте

Затем воспользуемся любым ZIP-архиватором и с его помощью создадим архив. В нашем примере таким архиватором будет WinRAR. В нем необходимо выбрать только что созданный файл и заархивировать его в формате ZIP:

Рис. 3. Создание архива с помощью архиватора WinRAR

После окончания архивирования на жестком диске компьютера в соответствующей директории появится новый файл «HelloWorld.zip». Первая особенность этого файла которая бросается в глаза — его размер, составляющий 135 байт, он гораздо больше первоначального размера исходного текстового файла в 11 байт. Это связано именно с тем, что помимо собственно упакованных данных, ZIP-архив содержит служебную информацию. Поэтому для небольших данных, занимающих всего несколько сот байтов, архивирование бессмысленно.

Теперь, когда у нас есть схема расположения данных, архив, состоящий из набора байтов, не покажется нам пугающим. Откроем его с помощью шестнадцатеричного редактора WinHex. На рисунке ниже представлен байтовый массив архива с условной подсветкой каждой области, описанной на схеме 1:

Рис. 4. Внутреннее содержимое ZIP-архива, содержащего файл HelloWorld.txt

Собственно фраза «HelloWorld!» содержится в диапазоне с 0x2B по 0x35 байт и занимает всего 11 байт. Обратите внимание, что алгоритм сжатия решил не сжимать исходную фразу, и в ZIP-архиве она присутствует в исходном виде. Это произошло потому, что сжатие такого короткого сообщения неэффективно, и сжатый массив может оказаться даже больше несжатого.

ZIP-архив не во всех случаях содержит сжатые данные. Иногда данные в архиве располагаются в исходном, несжатом виде, даже если при создании архива было явно указано сжимать данные при архивировании. Эта ситуация возникает в случае, когда размер данных незначителен, и сжатие данных неэффективно.

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

1.3. Структура Local File Header

Каждый ZIP-архив начинается со структуры Local File Header. Она содержит метаданные файла, следующего за ней в виде сжатого байтового массива. Каждая структура в архиве, согласно спецификации формата, имеет свой уникальный четырехбайтовый идентификатор. Не является исключением и эта структура, ее уникальный идентификатор равен 0x04034B50 .

Важно учитывать, что x86-совместимые процессоры загружают данные из бинарных файлов в оперативную память в обратном порядке. Числа при этом располагаются наизнанку: последний байт занимает место первого и наоборот. Способ записи данных в файл определяется форматом самого файла и для файлов в формате ZIP также осуществляется в обратном порядке. Более подробно о порядке следования байтов можно почитать в одноименной статье на Wikipedia: «Порядок байтов». Для нас же это означает, что идентификатор структуры будет записан в виде числа 0x504B0304 (значения 0x04034B50, вывернутого наизнанку). Именно с этой последовательности байтов начинается любой ZIP-архив.

Поскольку структура — это строго определенная последовательность байтов, ее можно представить в виде аналогичной структуры на языке программирования MQL5. Описание структуры Local File Header на MQL5 будет следующим:

Данная структура используется для реальной работы с ZIP-архивами, поэтому помимо собственно полей данных, содержит дополнительные методы, позволяющие конвертировать структуру в набор байтов (байтовый массив uchar) и, наоборот, создавать структуру из набора байтов. Приведем содержимое методов ToCharArray и LoadFromCharArray, позволяющих делать такое преобразование:

Опишем поля структуры (перечислены в порядке следования):

  • header — уникальный идентификатор стркутуры, для File Local Header равен 0x04034B50 ;
  • version — минимальная версия для распаковки файла;
  • bit_flag — битовый флаг, имеет идентификатор 0x02 ;
  • comp_method — тип используемого сжатия. Как правило, всегда используется метод сжатия DEFLATE, этот тип сжатия имеет идентификатор 0x08 .
  • last_mod_time — время последней модификации файла. Содержит часы, минуты и секунды модификации файла в формате MS-DOS. Этот формат описан на странице компании Microsoft.
  • last_mod_date — дата последней модификации файла. Содержит день месяца, номер месяца в году и год модификации файла в формате MS-DOS.
  • crc_32 — контрольная сумма CRC-32. Используется программами по работе с архивами для определения ошибок содержимого файла. Если это поле не заполнено, ZIP-архиватор откажется распаковывать упакованный файл, ссылаясь на испорченный файл.
  • comp_size — размер в байтах упакованных данных;
  • uncomp_size — размер в байтах исходных данных;
  • filename_length — длина имени файла;
  • extrafield_length — специальное поле для записи дополнительных атрибутов данных. Практически никогда не используется и равно нулю.

При сохранении этой структуры в архиве создается последовательность байтов, хранящая значения соответствующих полей этой структуры. Снова загрузим наш ZIP-архив с файлом HelloWorld.txt в шестнадцатеричный редактор и разберем байтовый массив этой структуры уже подробно:

Рис. 5. Байт-схема структуры Local File Header в архиве HelloWorld.zip

Из схемы видно, какие байты занимают те или иные поля структуры. Для проверки данных в ней обратим внимание на поле «File Name length», оно занимает два байта и равно значению 0x0D00 . Вывернув это число наизнанку и переведя его в десятичный формат, мы получим значение 13 — именно столько символов занимает имя файла «HelloWorld.txt». То же самое можем проделать с полем, указывающим размер сжатых данных. Оно равно 0x0B000000 , что соответствует 11 байтам. В самом деле, фраза «HelloWorld!» хранится в архиве в несжатом виде и занимает 11 байт.

Сразу после структуры идут сжатые данные, а затем начинается новая структура: Central Directory, ее мы опишем более подробно в следующем разделе.

1.4. Структура Central Directory

Структура Central Directory представляет собой расширенное представление данных, находящихся в Local File Header. По сути, для основной работы с ZIP-архивами достаточно данных из Local File Header. Тем не менее, использование структуры Central Directory является обязательным, и ее значения должны быть корректно заполнены. Эта структура имеет свой уникальный идентификатор 0x02014B50 . На MQL5 ее представление будет следующим:

Как видно, она содержит уже больше данных, однако большая часть из них дублирует данные Local File Header. Так же как и предыдущая структура, она содержит сервисные методы по конвертации своего содержимого в байт-массив и обратно.

  • header — уникальный идентификатор структуры, равен 0x02014B50 ;
  • made_ver — версия стандарта архивирования, используемого при архивировании;
  • version — минимальная версия стандарта для успешной распаковки файла;
  • bit_flag — битовый флаг, имеет идентификатор 0x02 ;
  • comp_method — тип используемого сжатия. Как правило, всегда используется метод сжатия DEFLATE, этот тип сжатия имеет идентификатор 0x08 .
  • last_mod_time — время последней модификации файла. Содержит часы, минуты и секунды модификации файла в формате MS-DOS. Этот формат описан на странице компании Microsoft.
  • last_mod_date — дата последней модификации файла. Содержит день месяца, номер месяца в году и год модификации файла в формате MS-DOS.
  • crc_32 — контрольная сумма CRC-32. Используется программами по работе с архивами для определения ошибок содержимого файла. Если это поле не заполнено, ZIP-архиватор откажется распаковывать упакованный файл, ссылаясь на испорченный файл.
  • comp_size — размер в байтах упакованных данных;
  • uncomp_size — размер в байтах исходных данных;
  • filename_length — длина имени файла;
  • extrafield_length — специальное поле для записи дополнительных атрибутов данных. Практически никогда не используется и равно нулю.
  • file_comment_length — длина комментария к файлу;
  • disk_number_start — номер диска, в который записывается архив. Практически всегда равен нулю.
  • internal_file_attr — атрибуты файла в формате MS-DOS;
  • external_file_attr — расширенные атрибуты файла в формате MS-DOS;
  • offset_header — адрес, по которому располагается начало структуры Local File Header.

При сохранении этой структуры в архиве создается последовательность байтов, хранящая значения ее полей. Приведем схему расположения байтов этой структуры, подобно рисунку 5:

Рис. 6. Байт-схема структуры Central Directory в архиве HelloWorld.zip

В отличие от Local File Header, структуры Central Directory идут последовательно друг за другом. Адрес начала первой из них указан в специальном завершающем блоке данных — структуре ECDR. Более подробно эту структуру мы опишем в следующем разделе.

1.5. Структура End of Central Directory Record (ECDR)

Структура End of Central Directory Record (или просто ECDR) завершает ZIP-файл. Ее уникальный идентификатор равен 0x06054B50 . В каждом архиве она содержится в единственном экземпляре. ECDR хранит количество файлов и директорий, находящихся в архиве, а также адрес начала последовательности структур Central Directory и их суммарный размер. Помимо этого, блок данных хранит и другие сведения. Приведем полное описание ECDR на MQL5:

Опишем поля этой структуры более подробно:

  • header — уникальный идентификатор структуры, равен 0x06054B50;
  • disk_number — номер диска;
  • disk_number_cd — номер диска, с которого начинается Central Directory;
  • total_entries_disk — всего записей в секции Central Directory (количество файлов и директорий);
  • total_entries — всего записей (количество файлов и директорий);
  • size_central_dir — размер секции Central Directory;
  • start_cd_offset — байт-адрес начала секции Central Directory;
  • file_comment_length — длина комментария к архиву.

При сохранении этой структуры в архиве создается последовательность байтов, хранящая значения ее полей. Приведем схему расположения байтов этой структуры:

Рис. 7. Байт-схема структуры ECDR

Этот блок данных будет использован нами при определении количества элементов в массиве.

Глава 2. Обзор класса CZip и его алгоритмов

2.1. Структура упакованных файлов в архиве, классы CZipFile и CZipFolder

Итак, в первой главе мы подробно разобрали формат ZIP-архива. Мы рассмотрели, из каких типов данных он состоит, и описали эти типы в соответствующих структурах. Определив эти типы, мы реализуем высокоуровневый специализированный класс CZip, с помощью которого можно будет легко и просто совершать следующие действия с ZIP-архивом:

  • Создавать новый архив;
  • Открывать ранее созданный архив на жестком диске;
  • Загружать архив с удаленного сервера;
  • Добавлять новые файлы в архив;
  • Удалять файлы из архива;
  • Распаковывать архив как полностью, так и отдельные его файлы.

Класс CZip возьмет на себя правильное заполнение необходимых структур в архиве, предоставляя нам привычный высокоуровневый интерфейс для работы с файловой коллекцией архива. Возможностей, предоставляемых классом, будет более чем достаточно для подавляющего большинства задач, связанных с архивированием.

Очевидно, что содержимое ZIP-архива можно разделить на папки и файлы. Оба типа содержимого имеют обширный набор свойств: имя, размер, атрибуты файла, время создания и т.д. Некоторые из этих свойств являются общими как для папок, так и для файлов, а некоторые, как, например, упакованные данные, нет. Поэтому оптимальным решением для работы с архивом будет предоставление специальных служебных классов: CZipFile и CZipDirectory. Именно эти классы будут представлять файлы и папки соответственно. Условная классификация содержимого в архиве приведена на схеме ниже:

Рис. 8. Условная классификация объектов в архиве

Таким образом, чтобы добавить файл в архив CZip, необходимо вначале создать объект типа CZipFile, а затем добавить этот объект-файл в архив. В качестве примера создадим текстовый файл «HelloWorld.txt», содержащий одноименный текст «HelloWorld!» и добавим его в архив:

После выполнения этого кода на диске компьютера появится новый ZIP-архив, содержащий единственный текстовый файл «HelloWorld.txt» с одноименной фразой. Если бы мы захотели создать папку вместо файла, то вместо CZipFile нам необходимо было бы создать экземпляр класса CZipFolder. Для его создания достаточно было бы указать только имя.

Как уже было сказано, классы CZipFile и CZipFolder имеют много общего. Поэтому оба класса наследуются от их общего прародителя — CZipContent. Этот класс содержит общие методы и данные для работы с содержимым архива.

2.2. Создание упакованных файлов с помощью CZipFile

Создание упакованного ZIP-файла тождественно созданию экземпляра CZipFile. Как известно, чтобы создать файл, необходимо указать его имя и содержимое. Поэтому конструктор CZipFile также требует явного указания соответствующих параметров:

В разделе 2.1 был показан вызов именно этого конструктора.

Кроме того, иногда требуется не создавать файл, а загрузить уже имеющийся файл с диска. Для этого случая в классе CZipFile существует второй конструктор, позволяющий создать ZIP-файл на основе обычного файла на жестком диске:

Вся работа в этом конструкторе делегируется приватному методу AddFile. Алгоритм его работы следующий:

  1. Открывается указанный файл для чтения, его содержимое считывается в байт-массив.
  2. Полученный байт-массив упаковывается методом AddFileArray и хранится в специальном динамическом массиве типа uchar.

Метод AddFileArray является «сердцем» всей системы классов для работы с архивами. Ведь именно в этом методе находится самая важная системная функция — CryptEncode. Приведем исходный код этого метода:

Желтым цветом указано конфигурирование функции CryptEncode c последующем архивированием байт-массива. Таким образом, можно сделать вывод, что упаковка файла происходит в момент создания объекта CZipFile, а не в момент создания или сохранения самого ZIP-архива, как можно было бы подумать. Благодаря этому свойству все данные, переданные в класс CZip, автоматически сжимаются, а значит, требуют для своего хранения меньше оперативной памяти.

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

Пользователю необходимо самостоятельно сконвертировать данные для хранения в архиве в беззнаковый массив uchar[], который, в свою очередь, также необходимо передать по ссылке в качестве содержимого файла для класса CZipFile. Благодаря этой особенности в ZIP-архиве может располагаться абсолютно любой тип файлов, как загруженный с диска, так и созданный в процессе работы MQL-программы.

Распаковка данных является более тривиальной задачей. Для распаковки данных в исходный байт массив file_array используется метод GetUnpackFile, который по сути является методом-обложкой для системной функции CryptDecode:

2.3. Вспоминаем MS-DOS. Формат времени и даты в ZIP-архиве

Формат хранения данных ZIP создавался в конце 80-ых годов прошлого века для платформы MS-DOS, «правопреемником» которой стала Windows. В то время ресурсы для хранения данных были ограничены, поэтому дату и время ОС MS-DOS хранила отдельно: два байта (или машинное слово для 16-разрядных процессоров того времени) выделялось для даты и два байта для времени. Причем самая ранняя дата, которая могла быть представлена этим форматом, была 1 января 1980 года (01.01.1980). Минуты, часы, дни, месяцы и годы занимали определенные диапазоны битов в машинном слове, и для того чтобы извлечь или записать их, по-прежнему приходится прибегать к битовым операциям.

Приведем формат хранения даты в соответствующем двухбайтовом поле:

№ битов Описание
0-4 День месяца (0-31)
5-8 Номер месяца (1 — январь, 2 — февраль и т.д.)
9-15 Номер года начиная с 1980

Таблица 1. Формат хранения даты в двухбайтовом поле

Аналогично, приведем формат хранения времени в соответствующем двухбайтовом поле:

№ битов Описание
0-4 Секунды (точностью хранения +/- 2 секунды)
5-10 Минуты (0-59)
11-15 Часы в 24-часовом формате

Таблица 2. Формат хранения времени в двухбайтовом поле

Зная спецификацию данного формата и умея работать с битовыми операциями, можно написать соответствующие функции, конвертирующие дату и время в формате MQL в формат MS-DOS. Можно также написать обратные процедуры. Такие методы конвертации общие как для папок, представленных CZipFolder, так и для файлов, представленных CZipFile. Задавая таким образом дату и время для них в привычном MQL формате, мы «за кулисами» конвертируем этот тип данных в формат MS-DOS. Таким конвертированием занимаются методы DosDate, DosTime, MqlDate и MqlTime. Приведем их исходный код.

Конвертация даты формата MQL в формат даты MS-DOS:

Конвертация даты в формате MS-DOS в формат MQL:

Конвертация времени формата MS-DOS в формат времени MQL:

Конвертация времени формата MS-DOS в формат времени MQL:

Данные методы используют внутренние переменные для хранения даты и времени: m_directory.last_mod_time и m_directory.last_mod_date, где m_directory — структура типа Central Directory.

2.4. Генерация контрольной суммы CRC-32

Интересной особенностью формата ZIP-архива является хранение, помимо служебных данных, специальной информации для восстановления, которая в некоторых случаях помогает восстановить поврежденные данные. Для того чтобы понять, являются ли полученные данные целыми или поврежденными, в ZIP-архиве содержится специальное дополнительное поле, хранящее двухбайтовое значение специального хеша CRC-32. Это контрольная сумма, которая рассчитывается для данных до упаковки. Архиватор, распаковав данных из архива, заново рассчитывает эту контрольную сумму, и если она не совпадает, считает, что данные повреждены и не могут быть предоставлены пользователю.

Таким образом, нашему классу CZip необходимо иметь свой собственный алгоритм расчета CRC-32. В противном случае архивы, созданные нашим классом, откажутся читать сторонние средства для работы с ними, например WinRAR выдаст ошибку-предупреждение о поврежденных данных:

Рис. 9. Предупреждение архиватора WinRAR о повреждении данных файла «HelloWorld.txt»

Поскольку контрольная сумма CRC-32 требуется только для файлов, метод, рассчитывающий эту сумму, представлен лишь в классе CZipFile. Метод реализован на основе примера на языке программирования Си, приведенного в статье по адресу: https://ru.wikibooks.org/wiki/Реализации_алгоритмов/Циклический_избыточный_код:

Чтобы убедиться в правильности работы метода, достаточно открыть архив, созданный с помощью CZip, в архиваторе WinRAR. Каждый файл будет иметь свой уникальный код CRC-32:

Рис. 10. Контрольная сумма CRC-32 в окне архиватора WinRAR

Файлы с корректным CRC-32 хешем архиватор распаковывает в штатном режиме, без появления соответствующих предупреждающих сообщений.

2.5. Чтение и запись архива

Последнее, что мы разберем, будут методы для чтения и записи самого ZIP-архива. Очевидно, что если у нас есть коллекция, например CArrayObj, состоящая из элементов CZipFile и CZipFolder, задача по формированию самого архива будет тривиальной. Достаточно каждый элемент сконвертировать в байт-последовательность и записать ее в файл. Этими задачами занимаются следующие методы:

  • SaveZipToFile — открывает указанный файл и записывает в него сгенерированный байт-массив архива.
  • ToCharArray — создает соответствующую байтовую структуру архива. Генерирует завершающую структуру ECDR.
  • ZipElementsToArray — преобразует элемент типа CZipContent в последовательность байтов.

Единственная сложность состоит в том, что каждый элемент архива, представленный типом CZipContent, хранится в двух разных частях файла, в структурах Local File Header и Central Directory. Поэтому необходимо использовать специальный вызов метода ZipElementsToArray, который в зависимости от переданного ему модификатора ENUM_ZIP_PART выдает либо байтовый массив типа Local File Header, либо Central Directory.

Теперь, учитывая эту особенность, нам должно быть понятно содержимое этих трех методов, исходный код которых представлен ниже:

Загрузка архива также обладает некоторыми нюансами. Очевидно, что загрузка архива — операция, обратная сохранению. Если при сохранении архива элементы типа CZipContent преобразуются в байтовую последовательность, то при загрузке архива байтовая последовательность преобразуется в элементы типа CZipContent. И снова, из-за того, что каждый элемент в архиве хранится в двух разных частях файла — Local File Header и Central Directory, элемент CZipContent за одно чтение данных создать невозможно.

Необходимо использовать промежуточный класс-контейнер CSourceZip, в который вначале последовательно добавляются нужные элементы, а затем на его основе формируется нужный тип данных — CZipFile или CZipFolder. Именно поэтому эти два класса имеют дополнительный конструктор, принимающий в качестве ссылочного параметра указатель на элемент типа CSourceZip. Данный вид инициализации, как и сам класс CSourceZip, создавался исключительно для служебного использования классом CZip, и его не рекомендуется использовать в явном виде.

За саму загрузку ответственны три метода класса CZip:

  • LoadZipFromFile — открывает указанный файл и читает его содержимое в байт-массив.
  • LoadHeader — загружает по предложенному адресу из байтового массива архива структуру Local File.
  • LoadDirectory — загружает по предложенному адресу из байтового массива архива структуру Central Directory.

Итак, приведем исходный код этих методов:

Глава 3. Примеры использования класса CZip, измерение производительности

В предыдущей главе мы рассмотрели класс CZip и собственно формат данных ZIP-архива. Теперь, зная устройство архива, а также общие принципы работы с классом CZip, мы можем перейти к рассмотрению практических задач, связанных с архивированием. В данной главе подробно рассмотрены три разносторонних примера, которые наиболее полно охватывают весь спектр задач этого класса.

3.1. Создание ZIP-архива с котировками по всем выбранным символам

Первая задача, которую часто требуется решать, это сохранение ранее полученных данных. Часто данные получаются в самом терминале MetaTrader. Такими данными могут быть последовательность накопленных тиков или котировки в формате OHLCV. Мы рассмотрим задачу, когда котировки требуется сохранить в специальные CSV-файлы, формат которых будет следующим:

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

Итак, давайте напишем скрипт, загружающий необходимые данные из терминала. Его алгоритм будет следующим:

  • Последовательно выбираются инструменты, размещенные в окне Market Watch.
  • По каждому выбранному инструменту запрашиваются котировки для каждого из 21 таймфрейма.
  • Котировки выбранного таймфрейма конвертируются в массив CSV строк.
  • Массив CSV строк конвертируется в байтовый массив.
  • Создается ZIP-файл (CZipFile), содержащий байтовый массив котировок, после чего он добавляется в архив.
  • После создания всех файлов котировок архив CZip сохраняется на диске компьютера в файл Quotes.zip.

Исходный код скрипта, выполняющий эти действия, представлен ниже:

Загрузка данных может занимать существенное время, поэтому в окне Market Watch были выбраны только четыре символа. Кроме того, мы загрузим лишь сто последних известных баров. Это тоже должно сократить время выполнения скрипта. После его выполнения в папке общих файлов MetaTrader появился архив Quotes.zip. Его содержимое можно увидеть в любой программе по работе с архивами, например WinRAR:

Рис. 11. Сохраненные файлы котировок, просматриваемые в архиваторе WinRAR

Созданный архив сжат втрое по сравнению с исходным размером. Об этом нам сообщает сам архиватор WinRAR:

Рис. 12. Степень сжатия сгенерированного архива в информационном окне WinRAR

Это хороший результат сжатия. Однако еще лучшего коэффициента сжатия удалось бы добиться на больших и немногочисленных файлах.

Пример скрипта, создающий котировки и сохраняющий их в zip архив прикреплен к данной статье под именем ZipTask1.mq5 и находится в папке Scripts.

3.2. Загрузка архива с удаленного сервера на примере сайта MQL5.com

Следующая рассматриваемая задача будет сетевой. Наш пример продемонстрирует, как можно загружать ZIP-архивы с удаленных серверов. В качестве примера мы произведем загрузку индикатора Alligator, находящегося в базе исходных кодов Code Base по адресу https://www.mql5.com/ru/code/9:

Для каждого опубликованного в Code Base индикатора, советника, скрипта или библиотеки существует архивная версия, где все исходные коды продукта упакованы в единый архив. Именно эту архивную версию мы скачаем и распакуем на локальном компьютере. Но прежде чем это сделать, необходимо поставить разрешение на доступ к mql5.com, для чего в окне Сервис Настройки Советники необходимо вписать адрес «https://www.mql5.com» в список разрешенных серверов.

Класс CZip обладает собственным методом для загрузки архивов с интернет-ресурсов. Но вместо его использования давайте напишем собственный скрипт, совершающий такую загрузку:

Как видите, исходный код скрипта довольно простой. Вначале вызывается WebRequest с адресом удаленного ZIP-архива. WebRequest закачивает байт-массив архива в результирующий массив zip_array, после чего он загружается в класс CZip посредством метода CreateFromCharArray. Этот метод позволяет создать архив прямо из последовательности байтов, что бывает иногда необходимым при внутренней работе с архивами.

Помимо метода CreateFromCharArray, CZip содержит специальный метод LoadZipFromUrl для загрузки архивов по интернет-ссылке. Он работает примерно так же, как и наш предыдущий скрипт. Приведем его исходный код:

Результат работы этого метода будет аналогичным: через некоторое время будет создан ZIP-архив, содержимое которого будет скачано с удаленного сервера.

Пример скрипта, загружающий архив из CodeBase прикреплен к данной статье под именем ZipTask2.mq5 и находится в папке Scripts.

3.3. Сжатие служебных данных программы в оперативной памяти компьютера

Сжатие внутренних данных программы в оперативной памяти компьютера — нетривиальный способ использования архивирования. Этот способ можно использовать, когда обрабатываемых данных слишком много для размещения в оперативной памяти. Однако при использовании данного подхода общая производительность программы снизится, ведь потребуются дополнительные действия по архивированию/разархивированию служебных структур или данных.

Предположим, что MQL-программе необходимо хранить коллекцию исторических ордеров. Каждый ордер будет описываться специальной структурой Order, которая будет содержать все его свойства: идентификатор, тип ордера, время исполнения, объем и т.д. Опишем данную структуру:

Вызов оператора sizeof показывает, что данная структура занимает 200 байт. Таким образом, хранение коллекции исторических ордеров занимает количество байт, рассчитанное по формуле: sizeof(Order) * количество исторических ордеров. Следовательно, для коллекции, насчитывающей 1000 исторических ордеров, потребуется выделение памяти 200 * 1000 = 200 000 байт или почти 200 Кбайт. Это немного по современным меркам, однако в случае, когда размер коллекции будет превышать десятки тысяч элементов, объем занимаемой памяти будет существенен.

Тем не менее, можно разработать специальный контейнер для хранения этих ордеров, который бы позволял сжимать их содержимое. Этот контейнер, помимо обычных методов добавления и удаления новых элементов Order, также будет содержать методы Pack и Unpack, сжимающие содержимое структур типа Order. Приведем исходный код данного контейнера:

Идея в том, что пользователь может добавлять новые элементы в контейнер, а также, в случае необходимости, сжимать его содержимое прямо в оперативной памяти компьютера. Посмотрим, как это работает. Напишем демонстрационный скрипт:

Момент сжатия коллекции в нем выделен желтым маркером. Запущенный на одном из счетов, насчитывающем 858 исторических ордеров, данный скрипт выдал следующие результаты:

Как видно, размер неупакованной коллекции составил 171 600 байт. После упаковки размер коллекции был равен всего 1 521 байт. Т.е. степень компрессии превысила сто раз! Это объясняется тем, что многие поля структуры содержат похожие данные. Также многие поля имеют пустые значения, под которые, тем не менее, выделяется память.

Чтобы убедиться, что сжатие действительно работает корректно, достаточно выбрать любой ордер из коллекции и распечатать его свойство. Нами был выбран первый ордер и его уникальный идентификатор. После упаковки идентификатор ордера отобразился верно:

Описываемый алгоритм в случае обращения к своей коллекции распаковывает ранее упакованные данные. Это снижает производительность. Поэтому сжимать данные нужно только после того, как работа по их формированию завершена. Для лучшей степени сжатия все данные собираются в единый массив, а затем упаковываются. Для распаковки происходит обратный процесс.

Интересно, что упаковка 858 элементов занимает около 2.5 миллисекунд на достаточно мощном компьютере. Распаковка этих же данных происходит еще быстрее и занимает порядка 0.9 миллисекунды. Таким образом, на один цикл упаковки/распаковки массива, состоящего из тысячи элементов, тратится примерно 3.5-4.0 миллисекунды. При этом достигается более чем стократная экономия памяти. Такие характеристики смотрятся достаточно впечатляюще, чтобы использовать ZIP-сжатие для организации больших массивов данных.

Пример скрипта, сжимающего данные в оперативной памяти, прикреплен к данной статье под именем ZipTask3.mq5 и находится в папке Scripts. Для его работы также необходим файл Orders.mqh, располагающийся в папке Include.

Глава 4. Документация к классам для работы с ZIP-архивами

4.1. Документация к классу CZipContent

В данной главе описаны методы и перечисления, используемые в классах для работы с ZIP-архивами. На уровне пользователей класс CZipContent не используется напрямую, однако все его открытые методы делегируются классам CZipFile и CZipFolder, таким образом, свойства и методы, описанные в нем, распространяются также и на эти классы.

Метод ZipType возвращает тип текущего элемента в архиве. Типов элементов, хранимых в архиве, два: папка (директория) и файл. Тип папки представлен классом CZipDirectory, тип файла представлен классом CZipFile. Более подробно о типах ZIP-архива можно прочитать в разделе 2.1 текущей главы: «Структура упакованных файлов в архиве, классы CZipFile и CZipFolder».

Возвращает перечисление ENUM_ZIP_TYPE, описывающее, к какому типу принадлежит текущий экземпляр CZipContent.

Возвращает название папки или файла в архиве.

Имя файла или папки.

Метод Name(string name)

Устанавливает название текущей папки или файла в архиве. Используется в случаях, когда требуется изменить имя текущей папки или файла.

  • [in] name — новое имя папки или файла. Имя должно быть уникальным и не иметь совпадений среди других имен папок и файлов в архиве.

Метод CreateDateTime(datetime date_time)

Устанавливает новую дату изменения папки или файла в архиве.

  • [in] date_time — дата и время, которое требуется установить для текущей папки или файла.

Дата и время конвертируются в формат MS-DOS и хранятся во внутренних структурах типа ZipLocalHeader и ZipCentralDirectory. Подробнее о способах конвертирования и представления этого формата описано в разделе 2.3 данной статьи: «Вспоминаем MS-DOS. Формат времени и даты в ZIP-архиве».

Возвращает дату и время изменения текущей папки или файла.

Дата и время изменения текущей папки или файла.

Возвращает размер упакованных данных в файле. Для директорий размер упакованных данных всегда равен нулю.

Размер упакованных данных в байтах.

Возвращает размер исходных, неупакованных данных в файле. Для директорий размер неупакованных данных всегда равен нулю.

Размер исходных данных в байтах.

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

Суммарный размер текущего элемента в архиве, учитывающий дополнительные служебные данные.

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

Длина имени директории или файла, выраженная в количестве используемых символов.

Распаковывает содержимое элемента и сохраняет его в файле с именем элемента на жестком диске компьютера. Если распаковывается директория, то вместо файла создается соответствующая папка.

  • [in] folder — имя корневой папки, в которую требуется распаковать текущую папку или файл. Если элемент требуется распаковать без создания папки архива, то это значение необходимо оставить пустым, равным «».
  • [in] file_common — этот модификатор указывает, в какой секции файловой системы программ MetaTrader необходимо распаковать элемент. Установите этот параметр равным FILE_COMMON, если хотите выполнить распаковку в общий файловый раздел всех терминалов MetaTrader 5.

Возвращает истину, если распаковка файла или папки на жесткий диск прошла успешно. Возвращает ложь в противном случае.

4.2. Документация к классу CZipFile

Класс CZipFile наследуется от CZipContent и используется для хранения файлов в архиве. CZipFile хранит содержимое файла только в упакованном виде. Это значит, что при передаче ему файла для хранения происходит автоматическая упаковка его содержимого. Распаковка файла также происходит в автоматическом режиме при вызове метода GetUnpackFile. Помимо ряда поддерживаемых методов CZipContent, CZipFile также поддерживает специальные методы для работы с файлами. Далее приведены описания этих методов.

Добавляет файл с жесткого диска в текущий элемент CZipFile. Для того чтобы добавить файл в архив типа CZip, вначале необходимо создать экземпляр класса CZipFile, указав при создании название файла и путь к нему. После того как экземпяляр класса будет создан, его необходимо будет добавить в класс CZip, вызвав соответствующий метод. Фактическая упаковка переданного содержимого происходит в момент его добавления (вызова данного метода).

  • [in] full_path — полное имя файла, включая путь к нему относительно центрального каталога файлов программ MQL.
  • [in] file_common — этот модификатор указывает, в какой секции файловой системы программ MetaTrader необходимо распаковать элемент. Установите этот параметр равным FILE_COMMON, если хотите выполнить распаковку в общий файловый раздел всех терминалов MetaTrader 5.

Возвращает истину, если добавление файл прошло успешно. Возвращает ложь в противном случае.

Добавляет в качестве содержимого CZipFile массив байтов типа uchar. Данный метод используется в случае динамического создания содержимого файла. Фактическая упаковка переданного содержимого происходит в момент его добавления (вызова данного метода).

  • [in] file_src — байтовый массив, который необходимо добавить.

Возвращает истину, если добавление файл прошло успешно. Возвращает ложь в противном случае.

Возвращает упакованное содержимое файла.

  • [out] file_array — байтовый массив, в который требуется принять упакованное содержимое файла.

Возвращает распакованное содержимое файла. Содержимое распаковывается в момент обращения к методу.

  • [out] file_array — байтовый массив, в который требуется принять распакованное содержимое файла.

4.3. Документация к классу CZip

Класс CZip реализует основную работу с архивами типа ZIP. Класс представляет собой обобщенный архив ZIP, в который могут быть добавлены ZIP-элементы двух типов: элементы, представляющие папку (CZipDirectory), и элементы, представляющие ZIP-файлы (CZipFile). Помимо прочего, класс CZip позволяет загружать уже существующие архивы, как с жесткого диска компьютера, так и в виде байт-последовательности.

Конвертирует содержимое ZIP-архива в байтовую последовательность типа uchar.

  • [out] zip_arch — байтовый массив, в который требуется принять содержимое ZIP-архива.

Загружает ZIP-архив из байтовой последовательности.

  • [out] zip_arch — байтовый массив, из которого требуется загрузить содержимое ZIP-архива.

Истина, если создание архива из байтовой последовательности прошло успешно, и ложь в противном случае.

Сохраняет текущий ZIP-архив с его содержимым в указанный файл.

  • [in] zip_name — полное имя файла, включая путь к нему относительно центрального каталога файлов программ MQL.
  • [in] file_common — этот модификатор указывает, в какой секции файловой системы программ MetaTrader необходимо распаковать элемент. Установите этот параметр равным FILE_COMMON, если хотите выполнить распаковку в общий файловый раздел всех терминалов MetaTrader 5.

Истина, если сохранение архива в файл прошла успешно, и ложь в противном случае.

Загружает содержимое архива из файла на жестком диске компьютера.

  • [in] full_path — полное имя файла, включая путь к нему относительно центрального каталога файлов программ MQL.
  • [in] file_common — этот модификатор указывает, в какой секции файловой системы программ MetaTrader необходимо распаковать элемент. Установите этот параметр равным FILE_COMMON, если хотите выполнить распаковку в общий файловый раздел всех терминалов MetaTrader 5.

Истина, если загрузка архива из файла прошла успешно, и ложь в противном случае.

Загружает содержимое архива по интернет-ссылке url. Для корректной работы данного метода необходимо выставить разрешение для доступа к запрашиваемому ресурсу. Более подробно работа этого метода описана в разделе 3.2 данной статьи: «Загрузка архива с удаленного сервера на примере сайта MQL5.com»

Распаковывает все файлы и директории текущего архива в предложенный каталог.

  • [in] folder — папка, в которую необходимо распаковать текущий архив. Если папку для архива создавать не требуется, в качестве параметра необходимо передать пустое значение «».
  • [in] file_common — этот модификатор указывает, в какой секции файловой системы программ MetaTrader необходимо распаковать элемент. Установите этот параметр равным FILE_COMMON, если хотите выполнить распаковку в общий файловый раздел всех терминалов MetaTrader 5.

Истина, если распаковка архива прошла успешно, и ложь в противном случае.

Возвращает размер архива в байтах.

Размер архива в байтах.

Возвращает количество элементов в архиве. Элементом архива может быть директория либо запакованный файл.

Количество элементов в архиве.

Добавляет новый ZIP-файл в текущий архив. Файл должен быть представлен в виде CZipFile и создан предварительно, до добавления в архив.

  • [in] file — ZIP-файл, который требуется добавить в архив.

Истина, если добавление в архив прошло успешно, и ложь в противном случае.

Удаляет файл типа CZipFile по индексу index из архива.

  • [in] index — индекс файла, который требуется удалить из архива.

Истина, если удаление файла из архива прошло успешно. Ложь в противном случае.

Получает элемент типа CZipFile, размещенный по индексу index.

  • [in] index — индекс файла, который требуется получить из архива.

Элемент типа CZipFile, который располагается по индексу index.

4.4. Структура ENUM_ZIP_ERROR и получение расширенной информации об ошибках

В процессе работы с классами CZip, CZipFile и CZipDirectory могут возникать различные ошибки, например ошибка, возникающая при попытке доступа к несуществующему файлу и т.д. Большинство методов, представленных в этих классах, возвращают соответствующий флаг типа bool, сигнализирующий об успешности совершения операции. В случае возвращения отрицательного значения (false) можно получить дополнительную информацию о причинах сбоя. Причинами сбоя могут быть как стандартные, системные ошибки, так и специфические ошибки, возникающие в процессе работы с ZIP-архивом. Для передачи специфических ошибок используется механизм передачи пользовательских ошибок с помощью функции SetUserError. Коды пользовательских ошибок задаются перечислением ENUM_ZIP_ERROR:

Значение Описание
ZIP_ERROR_EMPTY_SOURCE Файл, переданный для упаковки, пустой.
ZIP_ERROR_BAD_PACK_ZIP Ошибка внутреннего упаковщика/распаковщика.
ZIP_ERROR_BAD_FORMAT_ZIP Переданный формат ZIP-файла не соответствует стандарту либо испорчен.
ZIP_ERROR_NAME_ALREADY_EXITS Имя, под которым пользователь пытается сохранить файл, уже используется в архиве.
ZIP_ERROR_BAD_URL Переданная ссылка не ссылается на ZIP-архив, либо доступ к указанному интернет-ресурсу запрещен настройками терминала.

При получении пользовательской ошибки необходимо явно привести ее к перечислению ENUM_ZIP_ERROR и обработать соответствующим образом. Пример работы с ошибками, возникающими в ходе работы с классами архивирования, представлен ниже в виде скрипта:

4.5. Описание файлов, приложенных к статье

Ниже приведено краткое описание файлов, приложенных к статье:

  • Zip\Zip.mqh — содержит основной класс для работы с архивами CZip.
  • Zip\ZipContent.mqh — содержит базовый класс CZipContent для основных классов элементов архива: CZipFile и CZipDirectory.
  • Zip\ZipFile.mqh — содержит класс для работы с ZIP-файлами архива.
  • Zip\ZipDirectory.mqh — содержит класс для работы с ZIP-папками архива.
  • Zip\ZipHeader.mqh — в файле даны описания структур File Local Header, Central Directory и End Central Directory Record.
  • Zip\ZipDefines.mqh — перечислены определения, константы и коды ошибок, используемые при работе с классами по архивированию.
  • Dictionary.mqh — вспомогательный класс, обеспечивающий контроль уникальности имен файлов и директорий, добавляемых в архив. Алгоритм работы этого класса подробно описан в статье «Рецепты MQL5 — Реализуем ассоциативный массив или словарь для быстрого доступа к данным».

Все файлы, приведенные в статье, необходимо разместить относительно внутреннего каталога \MQL5\Include. Для начала работы с классом в проект необходимо включить файл Zip\Zip.mqh. Опишем в качестве примера скрипт, создающий ZIP-архив и записывающий в него текстовый файл с сообщением «test»:

После его выполнения на жестком диске компьютера в центральном каталоге файлов для MetaTrader 5 появится новый ZIP-архив с именем Test.zip, содержащий один текстовой файл с надписью «test».

Архив, прилагаемый к данной статье, создан с помощью MQL-архиватора CZip, который здесь описан.

Заключение

Мы подробно рассмотрели структуру ZIP-архива и создали классы, реализующие работу с этим типом архивов. Этот формат архивирования был разработан еще в конце 80-ых годов прошлого века, но это не мешает ему оставаться самым популярным форматом сжатия данных. Набор данных классов может оказать разработчику торговых систем неоценимую пользу. С его помощью можно экономно хранить собираемые данные, будь то тиковая история или другая торговая информация. Часто различная аналитическая информация также предоставляется в сжатом виде. В этом случае умение работать с такой информацией даже в сжатом виде также может оказаться полезным.

Описываемые классы скрывают многие технические аспекты работы с архивами, предоставляя на пользовательском уровне простые и понятные методы работы с ними, сходные с теми операциями, что привыкли совершать пользователи с программами архивирования: добавление и извлечение файлов из архива, создание новых и загрузка уже существующих архивов, в том числе размещенных на удаленных сторонних серверах. Эти возможности полностью решают большинство задач, связанных с архивированием, и делают программирование в среде MetaTrader еще проще и функциональнее.

Библиотека примеров приложений Java

Оглавление
Выбор файлов
Простейший редактор текста
Копирование файлов UNICODE
Сохранение объекта Java в файле
Произвольные классы и файлы
Буферизация потоков
Разбор конфигура-
ционного файла

Работа с консолью
Работа с классом PrintWriter
Разбор строк класса String
Загрузка и просмотр изображений
Потоки в оперативной памяти
Конвейерные потоки
Комбинирование двух потоков
Комбинирование нескольких потоков
Поиск слова в текстовом файле
Произвольный доступ к файлу
Информация о файле
Работа с каталогами
Просмотр содержимого каталога
Просмотр каталога с фильтром
Панель для выбора каталога
Список системных свойств
Сохранение списка системных свойств
Контрольная сумма файла
Копирование, переименование, удаление файлов
Архивы ZIP
Создание архива ZIP
Распаковка архива ZIP
Обход дерева каталогов

7.27. Работа с архивами формата ZIP

Показана методика просмотра содержимого архивных файлов формата ZIP, а также способ извлечения из такого архива отдельных файлов. Пример демонстрирует использование классов ZipFile и ZipEntry.

Немного теории

Среди различных библиотек классов Java есть одна очень интересная — с названием java.util.zip. Она позволяет работать с библиотеками файлов широко распространенных форматов ZIP и GZIP.

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

В этом разделе мы рассмотрим способы извлечения отдельных файлов из библиотеки формата ZIP и получения подробной информации о хранящихся там файлах.

Чтобы получить доступ к таким файлам, вы должны прежде всего создать объект класса ZipFile, пользуясь одним из конструкторов этого класса. Первый конструктор позволяет открыть ZIP-файл через объект класса File, а второй — через полный путь к имени файла:

В процессе создания объекта класса ZipFile могут возникать как обычные для файлов исключения IOException, так и исключения класса ZipException, специфические для класса ZipFile.

Класс ZipFile

В классе ZipFile определены несколько методов:

Метод Описание
entries Возвращает перечисление объектов, хранящихся в архивной библиотеке формата ZIP
getName Возвращает имя ZIP-файла
getInputStream Возвращает ссылку на входной поток для чтения объектов их архива
getEntry Возвращает объект, хранящийся в библиотеке, по его имени
close Закрывает ZIP-файл

Методы entries и getEntry позволяют получить элементы, хранящиеся в архиве, как объекты класса ZipEntry. Ниже мы получаем перечисление таких объектов:

Чтобы извлечь элементы перечисления и записать их в массив zipEntries класса Vector, мы можем создать цикл:

Класс ZipEntry

В классе ZipEntry определены две константы, конструктор и несколько методов.

Константы обозначают использованный метод компрессии:

Если файл сохранен в архиве без компрессии, для него используется метод ZipEntry.STORED, а если с компрессией — метод ZipEntry.DEFLATED.

Конструктор класса ZipEntry позволяет создать новый элемент оглавления архива с заданным именем:

Что же касается методов класса ZipEntry, то их можно разделить на две группы, одна из которых предназначена для установки атрибутов элемента оглавления архива ZIP, а другая — для извлечения.

Рассмотрим эти методы.

setCrc

Этот метод позволяет установить значение контрольной суммы для несжатого файла, описываемого данным элементом оглавления архива. Для вычисления контрольной суммы применяется алгоритм CRC-32.

getCrc

Предназначен для извлечения контрольной суммы, записанной в элемент оглавления.

setMethod

С помощью этого метода вы можете установить режим добавления файла в архив — с компрессией или без компрессии. В первом случае методу необходимо передать значение ZipEntry.DEFLATED, а во втором — значение ZipEntry.STORED.

getMethod

Метод getMethod позволяет знать способ компрессии, который был использован для файла, соответствующего данному элементу архива. Он может возвращать значения ZipEntry.DEFLATED или ZipEntry.STORED.

setExtra

С помощью этого метода можно записать в элемент оглавления архива произвольную дополнительную информацию.

getExtra

Метод getExtra возвращает дополнительную информацию, записанную в элементе оглавления архива.

setComment

Запись в элемент оглавления архива дополнительной текстовой строки комментария.

getComment

Чтение строки комментария.

getCompressedSize

Метод getCompressedSize возвращает размер сжатого файла или значение -1, если этот размер неизвестен.

isDirectory

Помимо файлов, в архиве могут хранится каталоги. В этом случае имя соответствующего элемента должно оканчиваться символом «/». Метод isDirectory позволяет узнать, является ли данные элемент описателем каталога или файла. В первом случае он возвращает значение true, а во втором — false.

getName

Этот метод позволяет узнать имя, соответствующее данному элементу оглавления архива. Изменить имя нельзя — оно передается конструктору класса ZipEntry при создании нового элемента оглавления.

setTime

Установка времени модификации файла (в количестве миллисекунд, прошедших с начала эпохи).

getTime

Определение времени модификации файла.

setSize

Установка размера несжатого файла.

getSize

Определение размера несжатого файла.

Описание примера

Наш пример автономного приложения ZipFileView создает одно главное окно класса Frame, в котором предусмотрено меню (рис. 1).

Рис. 1. Главное окно приложения

Строка Open меню File позволяет выбрать (с помощью стандартной диалоговой панели класса FileDialog) файл формата ZIP. Сразу после выбора такого файла на экране появляется диалоговая панель со списком имен элементов оглавления выбранного архива ZIP (рис. 2).

Рис. 2. Список элементов оглавления выбранного архива

Если выделить в этом списке любую строку, в главном окне приложения появится описание содержимого соответствующего элемента оглавления (рис. 1).

С помощью кнопки Extract вы сможете извлечь выделенный файл из архива и сохранить его на диске. Для выбора пути и имени сохраняемого файла наше приложение отобразит на экране стандартную диалоговую панель класса FileDialog.

Рассмотрим наиболее интересные фрагменты исходного текста приложения.

Прежде всего обратите внимание на классы, подключаемые оператором import:

Классы java.util.zip.* нужны для работы с файлами ZIP, а класс java.text.* — для форматирования строки даты изменения файлов, записанных в архиве.

Когда пользователь выбирает строку Open из меню File, метод actionPerformed, определенный в классе FrameWindow, отображает на экране стандартную диалоговую панель для выбора ZIP-файла:

Путь к выбранному файлу записывается в переменную szPath. Он затем передается конструктору класса ZipFileDialog, определенному в нашем приложении для отображения списка элементов оглавления ZIP-файла:

Класс ZipFileDialog

Класс ZipFileDialog создан на базе класса Dialog и реализует ряд интерфейсов:

В этом классе определено несколько полей.

В поле zf класса ZipFile хранится ссылка на объект, созданная для выбранного пользователем ZIP-файла:

Массив zipEntries класса Vector предназначен для хранения извлеченных элементов оглавления ZIP-файла:

Конструктор класса ZipFileDialog создает все необходимые компоненты и добавляют их в окно панели с применением режима размещения компонент GridBagLayout. Перед завершением своей работы он вызывает метод updateList:

Этот метод заполняет список, расположенный в окне панели, именами элементов оглавления архива.

Метод updateList класса ZipFileDialog

Рассмотрим исходный текст метода updateList, заполняющий список именами элементов оглавления архива.

Первым делом этот метод очищает список, удаляя из него все элементы:

Далее метод updateList выполняет все операции в блоке try-catch, что необходимо для обработки исключений.

Первым делом мы создаем объект класса ZipFile и с помощью метода entries получаем перечисление элементов оглавления архива:

Далее метод изменяет заголовок диалоговой панели, добавляя туда путь к выбранному архиву:

Пользуясь полученным перечислением мы заполняем массив zipEntries, записывая в него объекты класса ZipEntry:

Далее перебирая элементы массива zipEntries в цикле мы извлекаем имена элементов и добавляем их в список, расположенный в окне диалоговой панели:

Метод itemStateChanged класса ZipFileDialog

Когда пользователь выделяет в списке строку имени элемента оглавления массива, управление передается методу itemStateChanged, реализованному как часть интерфейса ItemListener:

Наша реализация этого метода вызывает метод getZipFileEntryInfo, извлекающий информацию из элемента оглавления архива и отображающий ее в главном окне приложения.

Метод getZipFileEntryInfo класса ZipFileDialog

Получив управление, метод getZipFileEntryInfo определяет номер элемента, выделенного пользователем в списке:

Далее из массива zipEntries извлекается соответствующий элемент класса ZipEntry:

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

Затем мы формируем новый текст в переменной szItemInfo, записывая туда значения атрибутов, извлеченные из элемента оглавления соответствующими методами класса ZipEntry:

Затем полученная строка добавляется в редактор главного окна приложения:

Метод actionPerformed класса ZipFileDialog

Когда пользователь нажимает кнопку Extract, расположенную в нижней части диалоговой панели со списком, метод actionPerformed извлекает из списка имя выделенного элемента архива и передает его методу saveZipFile:

Метод saveZipFile класса ZipFileDialog

В задачу метода saveZipFile входит извлечение из архива указанного файла и сохранение его на диске.

Прежде всего мы выделяем из полного пути к файлу имя:

Это имя затем используется при инициализации панели выбора выходного класса:

Таким образом, пользователю предлагается сохранить файл под тем именем, под которым он хранился в архиве.

Далее метод saveZipFile записывает полный путь к сохраняемому файлу в переменной szPath.

На следующем этапе метод создает выходной поток, связанный с файлом:

Узнав номер строки, выделенной пользователем в списке имен файлов, мы извлекаем из массива zipEntries соответствующий элемент оглавления класса ZipEntry:

Далее нам необходимо скопировать данные из архива в выходной файл fos.

Чтобы это сделать, мы получаем ссылку на входной поток, связанный с объектом ZipFile:

Копирование выполняется в цикле с применением методов read и write:

Учимся программировать на Java с нуля

ZIP-архивы в языке Java

ZIP-архивы позволяют хранить один и более файлов в (обычно) сжатом формате. У каждого ZIP-архива имеется заголовок, содеражащий информацию вроде имени файла или использовавшегося для него метода сжатия. В Java для чтения ZIP-архивов применяется класс ZipInputStream. В каждом таком архиве всегда требуется просматривать отдельные записи(entries).

Метод getNextEntry возвращает описывающий запись объект типа ZipEntry. Метод read класс ZipInputStream изменяется так, чтобы он возвращал -1 в конце текущий записи(а не просто в конце ZIP-файла).

Далее вызывается метод closeEntry для получения возможности перехода к считыванию следующей записи. Ниже приведена типичная кодовая последовательность для выполнения считывания содержимого ZIP-файла:

Для считывания содержимого конкретной записи из ZIP-файла эффективнее использовать не стандартный метод read, а методы какого-то обладающего большими находящегося внутри ZIP-архива, можно применить следующий цикл:

В случае возникновения ошибки при считывании ZIP-файла класс ZipInputStream выдает исключение ZipException. Обычно подобное происходит при повреждении ZIP-файла.

Для записи ZIP-файла применяется класс ZipOutputStream. Для каждой записи, которую требуется поместить в ZIP-файл, создается объект ZipEntry. Желаемое имя для файла передается конструктору ZipEntry, тот устанавливает остальные параметры, вроде даты создания файла и метода распаковки.

При желании эти параметры могут переопределяться. Далее вызывается метод putNextEntry класса ZipOutputStream для начала процесса записи нового файла. После этого данные самого файла отправляются потоку ZIP. По завершении вызывается метод closeEntry. Затем все эти действия выполняются повторно для всех остальных файлов, которые требуется сохранить в ZIP-архиве. Ниже приведена общая схема необходимого кода:

JAR-файлы представляют собой те же ZIP-файлы, но только содержат записи несколько иного вида, называемые манифестом. Для считывания и записи манифестов применяются классы JarInputStream и JarOutputStream.

ZIP-потоки являются прекрасным примером мощи потоковой абстракции. При считывании данных, которые хранятся в сжатом виде, не нужно волноваться о том, будут ли они распаковаться по мере запрашивания. И источником байтов в ZIP-форматах вовсе не обязательно должен быть именно файл: ZIP-данные могут поступать и через сетевое подключение. На самом деле, при всяком считывании JAR-файла загрузчик классов аплета будет считывать и распаковывать данные именно из сети.

Рис.2. Программа ZipTest

Программа код которой приведен ниже, позволяет открывать ZIP-архив, после чего отображает все хранящиеся внутри него файлы в комбинированном списке в нижней части экрана. В случае выбора какого-то одного из этих файлов она отображает его содержимое в текстовой области, как показано на рис.2.

code entry

Универсальный англо-русский словарь . Академик.ру . 2011 .

Смотреть что такое «code entry» в других словарях:

Code coverage — is a measure used in software testing. It describes the degree to which the source code of a program has been tested. It is a form of testing that inspects the code directly and is therefore a form of white box testing.[1] Code coverage was among … Wikipedia

Code page 437 — Code page 437, as rendered by the IBM PC using a VGA adapter. IBM PC or MS DOS code page 437, often abbreviated CP437 and also known as DOS US, OEM US or sometimes misleadingly referred to as the OEM font, High ASCII or Extended ASCII,[1][2] is… … Wikipedia

code-named — codeˈ named adjective • • • Main Entry: ↑code * * * ˈcode named ; adjective not before noun • a drug investigation, code named Snoopy … Useful english dictionary

Code of Personal Status (Tunisia) — The Code of Personal Status (CPS) (Arabic: مجلة الأحوال الشخصية‎) is a series of progressive Tunisian laws aiming at the institution of equality between women and men in a number of areas. It was promulgated by beylical decree on August 13, 1956… … Wikipedia

code of practice — code of conduct or code of practice noun An established method or set of rules for dealing with, behaving in, etc a particular situation • • • Main Entry: ↑code * * * code of practice UK US noun [countable] [singular code of practice … Useful english dictionary

code-sharing — codeˈ sharing noun A system by which two airlines independently sell seats on the same flight • • • Main Entry: ↑code * * * ˈcode sharing 7 [code sharing] noun uncountable … Useful english dictionary

Code to Zero — 1st edition … Wikipedia

code-number — codeˈname or codeˈ number noun A name or number used for convenience, economy, secrecy, etc • • • Main Entry: ↑code … Useful english dictionary

code-breaker — codeˈ breaker noun A person who tries to interpret secret codes • • • Main Entry: ↑code … Useful english dictionary

code-breaking — codeˈ breaking noun • • • Main Entry: ↑code … Useful english dictionary

Code for Sustainable Homes — The Code for Sustainable Homes is an environmental impact rating system for housing in England and Wales, setting new standards for energy efficiency (above those in current building regulations)[1] and sustainability which are not mandatory… … Wikipedia

Илон Маск рекомендует:  Что такое код msql_list_tables
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL