Работа с ZIP-архивами из-под lisp’a

Понадобилось мне тут обрабатывать zip-архивы. Казалось бы, все должно быть просто, поскольку обработка zip-архивов уже в Windows встроена. Ан нет, ни фига.

Недолгий поиск привел на темы http://www.theswamp.org/index.php?topic=37416.0 и http://www.theswamp.org/index.php?topic=31097.msg366864#msg366864. И я радостно стал использовать представленные там коды.

Правда, счастье было неполным и очень недолгим. Причин оказалось несколько: как выяснилось, только операции с одиночными файлами (заархивировать, распаковать и т.п.) выполняются на ура. Как только надо обработать что-то пакетно (запаковать, например, каталог со всеми подкаталогами; или распаковать) - начинаются чудеса. И заключаются они в том, что при пакетной обработке какие-то файлы могут запросто не заархивироваться. Или не распаковаться.

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

Так, для распаковки можно сделать vbs-файл и заставить его выполняться:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(defun _kpblc-zip-extract-allfiles (zipfile strdest / file handle wscript)
                                  ;|
*    Извлечение всех файлов из zip-архива (включая подкаталоги). Источник:
* http://www.theswamp.org/index.php?topic=31097.0
*    Параметры вызова:
  zipfile     Полное имя zip-архива
  strdest     Путь, куда выполнять разархивирование.
*    Пример вызова:
(_kpblc-zip-extract-allfiles "C:\\pack.zip" "C:\\updates")
|;
 (setq file   (strcat (vl-string-right-trim "\" (getenv "temp")) "\\unzip.vbs")
          handle (open file "
w")
          ) ;_ end of setq
    (foreach item (list (strcat "
ZipFile="" zipfile """)
                        (strcat "
ExtractTo="" strdest """)
                        "
'If the extraction location does not exist create it."
                        "
Set fso = CreateObject("Scripting.FileSystemObject")"
                        "
If NOT fso.FolderExists(ExtractTo) Then"
                        "
  fso.CreateFolder(ExtractTo)"
                        "
End If"
                        "
'Extract the contants of the zip file."
                        "
set objShell = CreateObject("Shell.Application")"
                        "
set FilesInZip=objShell.NameSpace(ZipFile).items"
                        "
objShell.NameSpace(ExtractTo).CopyHere(FilesInZip)"
                        "
Set fso = Nothing"
                        "
Set objShell = Nothing"
                        ) ;_ end of list
      (write-line item handle)
      ) ;_ end of foreach
    (close handle)
    (if (setq wscript (vlax-get-or-create-object "
WScript.Shell"))
      (vl-catch-all-apply (function (lambda () (vlax-invoke-method wscript "
Run" file 0 :vlax-true))))
      ) ;_ end of if
    (vl-catch-all-apply (function (lambda () (vlax-release-object wscript))))
    (vl-file-delete file)
    ) ;_ end of defun

Честно скажу, код VBS не мой, спер откуда-то.
Чем хорош подобный код - так это тем, что каталог вроде бы даже и создавать предварительно не надо, эту работу выполнит VBS. Чем плох - так это тем, что админы "с добрыми усталыми глазами и печальной улыбкой на лице" могут заблокировать выполнение VBS-кода. Ну, если заблокируют, буду придумывать что-нибудь еще.

С архивированиеи я решил задачу по-другому. Попытался в очередной раз использовать C#:
{cc lang="csharp"]using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;

using AcRt = Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;

namespace kpblc
{
[AcRt.LispFunction("_kpblc-zipfolder")] public static bool kpblc_zipfolder(AcDb.ResultBuffer arguments)
{
bool res = false ;
if (arguments != null)
{
Array args = arguments.AsArray();
string zipDest = System.Convert.ToString(((AcDb.TypedValue)(args.GetValue(0))).Value);
string folderName = System.Convert.ToString(((AcDb.TypedValue)(args.GetValue(1))).Value);
try
{
ZipFile.CreateFromDirectory(folderName, zipDest, CompressionLevel.Optimal, false);
res = true;
}
catch
{
res = false;
}
}
return res;
}

}
}[/cc] Сборка всяко загружается внутрь ACAD'a, так что можно спокойно использовать _kpblc-zipfolder и не париться.

Размещено в .NET, AutoCAD, Код LISP, Функции LISP · Метки: , , ,



Поделитесь своим мнением


Я не робот.