最近做个发邮件的功能,需要将日志文件通过邮件发送回来用于分析,但是日志文件可能会超级大,测算下来一天可能会有800M的大小。所以压缩是不可避免了,delphi中的默认压缩算法整了半天不太好使,就看了看7z,在windows下有dll那么就用它吧。

下载7z.dll,还有一个delphi的开发sdk文件,sevenzip.pas。有这两个就可以了。

压缩

使用超级简单

procedure TForm1.Button1Click(Sender: TObject);
var
Arch: I7zOutArchive;
Counter: Integer;
sZipFile: string;
begin
OpenDialog1.Filter := '所有文件|*.*';
OpenDialog1.Options := OpenDialog1.Options + [ofAllowMultiSelect];
if OpenDialog1.Execute then
begin
Memo1.Lines.Append('开始压缩');
Arch := CreateOutArchive(CLSID_CFormat7z);
Arch.SetProgressCallback(nil, ProgressCallback);
for Counter := to OpenDialog1.Files.Count - do
Arch.AddFile(OpenDialog1.Files[Counter], ExtractFileName(OpenDialog1.Files[Counter])); SetCompressionLevel(Arch, );
SevenZipSetCompressionMethod(Arch, m7LZMA);//算法设置,很重要哦
sZipFile := FRootPath+'test.7z';
Arch.SaveToFile(sZipFile);
Memo1.Lines.Append('完成压缩,文件生成于:' + sZipFile);
CalcZipScale(sZipFile, ProgressBar1.Max);
end;
end;

此方法通过文件选择框可以压缩多个文件成一个压缩包。这里有点要注意的是使用:m7LZMA这个算法压缩比特别高,好像针对文本类型的会很好。我试了400M的文本压缩后5M左右吧。这个压缩率还是挺可观的。

另外有个需求是用于压缩整个目录的,方法也很简单:

procedure TForm1.Button3Click(Sender: TObject);
var
Arch: I7zOutArchive;
Counter: Integer;
sZipFile: string;
begin
if not DirectoryExists(edtPath.Text) then
begin
ShowMessage('请输入有效目录');
edtPath.SetFocus;
end; Memo1.Lines.Add('开始压缩');
Arch := CreateOutArchive(CLSID_CFormat7z);
Arch.SetProgressCallback(nil, ProgressCallback);
Arch.AddFiles(edtPath.Text, 'memData', '*.*', False); SetCompressionLevel(Arch, );
SevenZipSetCompressionMethod(Arch, m7LZMA);//算法设置,很重要哦
sZipFile := FRootPath+'path.7z';
Arch.SaveToFile(sZipFile);
Memo1.Lines.Append('完成压缩,文件生成于:' + sZipFile);
CalcZipScale(sZipFile, ProgressBar1.Max);
end;

没什么大的区别,就是调用压缩方法时使用AddFiles,这个方法的参数要注意一下:

procedure AddFiles(const Dir, Path, Wildcard: string; recurse: boolean); stdcall;

Dir:待压缩的目录

Path:压缩包中的目录(就是压缩后在压缩包里的根目录)

Wildcard:通配符,可以用于过滤文件(*.*)

recurse:递归子目录

其他的压缩我就没去试了,生成7z的包用winrar反正是可以打开和解压的。

解压

7z也提供了解压的算法,但是不同的压缩算法生成的压缩包格式是不同的,需要指定解压类型来解压。但我看7z里支持的算法类型还是很全的,于是就整了个If列表。

先看看解压的方法:

procedure TForm1.Button2Click(Sender: TObject);
var
Arch: I7zInArchive;
Counter: Integer;
sExtractPath: string;
begin
OpenDialog1.Filter := '压缩文件|*.zip;*.rar;*.7z';
OpenDialog1.Options := OpenDialog1.Options - [ofAllowMultiSelect];
if OpenDialog1.Execute then
begin
Memo1.Lines.Append('开始解压');
try
Arch := GetInArchiveByFileExt(ExtractFileExt(OpenDialog1.FileName));
Arch.SetProgressCallback(nil, ProgressCallback);
Arch.OpenFile(OpenDialog1.FileName);
for Counter := to Arch.NumberOfItems - do
begin
if not Arch.ItemIsFolder[Counter] then
Memo1.Lines.Append('包含文件:' + Arch.ItemPath[Counter]);
end; sExtractPath := FRootPath + getShotFileName(ExtractFileName(OpenDialog1.FileName));
if ForceDirectories(sExtractPath) then
begin
Arch.ExtractTo(sExtractPath);
Memo1.Lines.Append('完成解压');
end
else
ShowMessage('无法解压到指定目录');
except
on e: Exception do
Memo1.Lines.Add('发生异常:' + e.Message)
end; Arch := nil;
Memo1.Lines.Add('-----------------------------------------------------------');
end;
end;

解压时是调用ExtractTo来解压的,简单。只不过要通过后缀来选择特定的解压对象需要单独处理一下,写了个方法:

function TForm1.GetInArchiveByFileExt(AExt: string): I7zInArchive;
var
sExt: string;
begin
sExt := UpperCase(AExt);
if (sExt='.ZIP') or (sExt='.JAR') or (sExt='.XPI') then
Result := CreateInArchive(CLSID_CFormatZip)
else if (sExt='.BZ2') or (sExt='.BZIP2') or (sExt='.TBZ2') or (sExt='.TBZ') then
Result := CreateInArchive(CLSID_CFormatBZ2)
else if (sExt='.RAR') or (sExt='.R00') then
Result := CreateInArchive(CLSID_CFormatRar)
else if (sExt='.ARJ') then
Result := CreateInArchive(CLSID_CFormatArj)
else if (sExt='.Z') or (sExt='.TAZ') then
Result := CreateInArchive(CLSID_CFormatZ)
else if (sExt='.LZH') or (sExt='.LHA') then
Result := CreateInArchive(CLSID_CFormatLzh)
else if (sExt='.7Z') then
Result := CreateInArchive(CLSID_CFormat7z)
else if (sExt='.CAB') then
Result := CreateInArchive(CLSID_CFormatCab)
else if (sExt='.NSIS') then
Result := CreateInArchive(CLSID_CFormatNsis)
else if (sExt='.LZMA') then
Result := CreateInArchive(CLSID_CFormatLzma)
else if (sExt='.LZMA86') then
Result := CreateInArchive(CLSID_CFormatLzma86)
else if (sExt='.EXE') then
Result := CreateInArchive(CLSID_CFormatPe)
else if (sExt='.PE') or (sExt='.DLL') or (sExt='.SYS') then
Result := CreateInArchive(CLSID_CFormatPe)
else if (sExt='.ELF') then
Result := CreateInArchive(CLSID_CFormatElf)
else if (sExt='.MACHO') then
Result := CreateInArchive(CLSID_CFormatMacho)
else if (sExt='.UDF') then
Result := CreateInArchive(CLSID_CFormatUdf)
else if (sExt='.XAR') then
Result := CreateInArchive(CLSID_CFormatXar)
else if (sExt='.MUB') then
Result := CreateInArchive(CLSID_CFormatMub)
else if (sExt='.HFS') or (sExt='.CD') then
Result := CreateInArchive(CLSID_CFormatHfs)
else if (sExt='.DMG') then
Result := CreateInArchive(CLSID_CFormatDmg)
else if (sExt='.MSI') or (sExt='.DOC') or (sExt='.XLS') or (sExt='.PPT') then
Result := CreateInArchive(CLSID_CFormatCompound)
else if (sExt='.WIM') or (sExt='.SWM') then
Result := CreateInArchive(CLSID_CFormatWim)
else if (sExt='.ISO') then
Result := CreateInArchive(CLSID_CFormatIso)
else if (sExt='.BKF') then
Result := CreateInArchive(CLSID_CFormatBkf)
else if (sExt='.CHM') or (sExt='.CHI') or (sExt='.CHQ') or (sExt='.CHW')
or (sExt='.HXS') or (sExt='.HXI') or (sExt='.HXR') or (sExt='.HXQ')
or (sExt='.HXW') or (sExt='.LIT') then
Result := CreateInArchive(CLSID_CFormatChm)
else if (sExt='.001') then
Result := CreateInArchive(CLSID_CFormatSplit)
else if (sExt='.RPM') then
Result := CreateInArchive(CLSID_CFormatRpm)
else if (sExt='.DEB') then
Result := CreateInArchive(CLSID_CFormatDeb)
else if (sExt='.CPIO') then
Result := CreateInArchive(CLSID_CFormatCpio)
else if (sExt='.TAR') then
Result := CreateInArchive(CLSID_CFormatTar)
else if (sExt='.GZ') or (sExt='.GZIP') or (sExt='.TGZ') or (sExt='.TPZ') then
Result := CreateInArchive(CLSID_CFormatGZip)
else
Result := CreateInArchive(CLSID_CFormatZip);
end;

没想到7z的完成度这么高,还是非常方便的。

后记:以前在.net平台上调用过7z,只不过是使用shell方式调用的7z.exe。用命令感觉会麻烦一些,使用dll集成在程序中还是挺方便的。

学习笔记:7z在delphi的应用的更多相关文章

  1. 转:学习笔记: Delphi之线程类TThread

    学习笔记: Delphi之线程类TThread - 5207 - 博客园http://www.cnblogs.com/5207/p/4426074.html 新的公司接手的第一份工作就是一个多线程计算 ...

  2. 转:学习笔记:delphi多线程学识

    学习笔记:delphi多线程知识 最近一直在温习旧的知识,刚好学习了一下Java的线程安全方面的知识,今天想起之前一直做的Delphi开发,所以还是有必要温习一下,看看这些不同的编程语言有什么不同之处 ...

  3. Delphi 对象模型学习笔记(转)

    摘要     Borland Object Pascal 对象模型(现在已经正是命名为 Delphi 语言)与其他 OOP 语言一样,都提供了一些基础服务: 如对象创建服务.对象释放服务.对象识别服务 ...

  4. delphi操作xml学习笔记 之一 入门必读

    Delphi 对XML的支持---TXMLDocument类       Delphi7 支持对XML文档的操作,可以通过TXMLDocument类来实现对XML文档的读写.可以利用TXMLDocum ...

  5. 转)delphi chrome cef3 控件学习笔记 (二)

    (转)delphi chrome cef3 控件学习笔记 (二) https://blog.csdn.net/risesoft2012/article/details/51260832 原创 2016 ...

  6. 【工作笔记】BAT批处理学习笔记与示例

    BAT批处理学习笔记 一.批注里定义:批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD,这些命令统称批处理命令. 二.常见的批处理指令: 命令清单: 1.RE ...

  7. NSIS学习笔记(转)

    转自:http://blog.csdn.net/lee353086/article/details/45919901 NSIS学习笔记Date:2015-05-20Author:kagulaEnv:V ...

  8. thrift学习笔记

    Thrift学习笔记 一:thrift介绍 Thrift是facebook开发的用来处理各不同系统之间数据通讯的rpc服务框架,后来成为apche的开源项目.thrift支持多种程序语言,包括Java ...

  9. MySQL存储过程学习笔记

    MySQL在5.0以前并不支持存储过程,这使得MySQL在应用上大打折扣.MySQL 5.0终于开始支持存储过程了. MySQL的关键字大小写通用.该学习笔记对关键字使用大写:变量名,表名使用小写. ...

  10. CSS学习笔记——盒模型,块级元素和行内元素的区别和特性

    今天本来打算根据自己的计划进行前端自动化的学习的,无奈早上接到一个任务需求需要新增一个页面.自从因为工作需要转前端之后,自己的主要注意力几 乎都放在JavaScript上面了,对CSS和HTML这方面 ...

随机推荐

  1. C语言 · 薪水计算

    问题描述 编写一个程序,计算员工的周薪.薪水的计算是以小时为单位,如果在一周的时间内,员工工作的时间不超过40 个小时,那么他/她的总收入等于工作时间乘以每小时的薪水.如果员工工作的时间在40 到50 ...

  2. ASP.NET Core的路由[4]:来认识一下实现路由的RouterMiddleware中间件

    虽然ASP.NET Core应用的路由是通过RouterMiddleware这个中间件来完成的,但是具体的路由解析功能都落在指定的Router对象上,不过我们依然有必要以代码实现的角度来介绍一下这个中 ...

  3. 高频交易算法研发心得--MACD指标算法及应用

    凤鸾宝帐景非常,尽是泥金巧样妆. 曲曲远山飞翠色:翩翩舞袖映霞裳. 梨花带雨争娇艳:芍药笼烟骋媚妆. 但得妖娆能举动,取回长乐侍君王. [摘自<封神演义>纣王在女娲宫上香时题的诗] 一首定 ...

  4. 应该是Angular2的一个bug?

    为了应对未来的趋势,及时赶上下一趟互联网技术,我最近也在通过具体项目研究angular2,首先必须要吐槽的是,学习angular2的成本本身不高,但是一堆的工具.配置实在让人 很是焦灼,就像asp.n ...

  5. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  6. Javascript高性能编程-提高Dom访问速度

    在浏览器中对于Dom的操作和普通的脚本的操作处于两个不同的dll中,两个dll的交互是比较耗时的,优化对Dom的操作可以提高脚本的执行速度.下面是对如何优化的一些总结: 将需要多次操作的节点存储在一个 ...

  7. arcgis api for js入门开发系列六地图分屏对比(含源代码)

    上一篇实现了demo的地图标绘模块,本篇新增地图地图分屏对比模块,截图如下(源代码见文章底部): 对效果图的简单介绍一下,在demo只采用了两分屏对比,感兴趣的话,可以在两分屏的基础上拓展,修改css ...

  8. BPM配置故事之案例7-公式计算

    行政主管发来邮件.要求物资明细表增加"单价""总价"."单价"由其审批时填写,"总价"根据"单价"与 ...

  9. Android:Activity+Fragment及它们之间的数据交换.

    Android:Activity+Fragment及它们之间的数据交换 关于Fragment与Fragment.Activity通信的四种方式 比较好一点的Activity+Fragment及它们之间 ...

  10. Xamarin Android 应用程序内图标上数字提示

    最近在用 Xamarin 做一个 Android 应用,打开应用时,如果有新消息,需要在应用内的 Toolbar 或者首页的图标上显示数字提示.在这里和大家分享一下实现方法,如果你有更新好的实现方法, ...