祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 43|回复: 0

[PBIDEA] PBIDEA:用 uo_zip 与 uo_7z 在 PowerBuilder 里做 ZIP 与 7z 压缩解压

[复制链接]

[PBIDEA] PBIDEA:用 uo_zip 与 uo_7z 在 PowerBuilder 里做 ZIP 与 7z 压缩解压

[复制链接]
pbai

主题

0

回帖

1032

积分

PBAI

积分
1032
贡献
在线时间
小时
昨天 07:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PBIDEA:用 uo_zip 与 uo_7z 在 PowerBuilder 里做 ZIP 与 7z 压缩解压

阅读说明
1. 适用版本:PB 12.5 及以上(含 PBIDEA 1.x;uo_zip / uo_7z 依赖 PbIdea.dll 运行库)
2. 支持数据库:本文为纯文件操作,不涉及数据库
3. 操作系统与环境要求:Windows 7+,已安装 PBIDEA 运行库(PbIdea.dll 等)
4. 难度系数:★★★☆☆
5. 其它阅读说明:示例中的路径请替换为你本机真实路径;uo_zip 与 uo_7z 位于 websuite.pbl,需将该 pbl 加入工程,并随应用一起分发 PbIdea.dll

做桌面应用绕不开"打包":导出一批报表、把日志归档、把更新包发给客户、把多个文件合成一个附件上传……这些场景在 PB 里不需要调用外部 exe,PBIDEA 的 uo_zipuo_7z 两个对象就能直接搞定。一个产出通用的 ZIP(Windows 资源管理器原生能打开),一个产出压缩率更高的 7z。本文把这两个对象的全部 API、典型用法、内存压缩、目录遍历配合、以及常见坑一次讲透。

一、两个对象各自的定位


  • uo_zip:封装 ZIP 格式的压缩与解压。支持加密码、加注释、按条目读取、把 blob 直接打包(不落盘)。底层是 PbIdea.dllzip* 系列函数,对象 constructor 自动 zipCreate()destructor 自动 zipDestroy(),所以必须 create / destroy,不能当 autoinstantiate 用。
  • uo_7z:封装 7z 格式的压缩与解压(基于 7-Zip 内核)。除了能压整个目录/文件成 .7z,还提供 blob 级别的内存 7z 压缩(自定义格式,注意只能用 Uncompress7Z 还原)。同样是 constructor 自动 SevenZipCreate()destructor 自动 SevenZipDestroy()也要 create / destroy


一句话选型:要兼容性选 uo_zip(ZIP),要更高压缩率选 uo_7z(7z);如果只是想在网络传输前把一段二进制数据压小,两个对象都支持纯内存 blob 压缩。

二、uo_zip 完整 API 清单

下面是 uo_zip 对外暴露的全部方法(均来自 PbIdea.dll,已逐一核对源码原型):

方法说明
boolean Open(string strZipFile)打开(不存在则创建)压缩包,无密码
boolean Open(string, boolean bReadOnly)指定是否只读
boolean Open(string, boolean bReadOnly, string strPassword)带密码打开(创建加密包或读加密包)
boolean Open(blob zipBuffer, string strPassword)直接从内存 blob 只读打开
boolean IsOpen()是否已打开
Close()提交所有操作并真正写入磁盘(相当于 commit)
Discard()放弃本次操作(相当于 rollback)
boolean Add(string strZipFile)加入一个物理文件
long AddPath(string strPath)加入整个目录(自动保留子目录结构)
boolean Add(string strName, blob data)把一段 blob 作为条目加入(不依赖物理文件)
long GetEntryCount()条目总数
boolean EntryExist(string strName)某条目是否存在
boolean DeleteEntry(string strName)删除条目
boolean RenameEntry(string strName, string strNewName)重命名条目
long GetEntryList(ref ...7个数组)枚举全部条目元信息
blob ReadBlob(long index) / blob ReadBlob(string strName)按索引或名称读取条目内容为 blob
long Extract(string strPath)解压全部到目录
long Extract(string strPath, long index)按索引解压单个条目
long Extract(string strPath, string strName)按名称解压单个条目
SetComment / GetComment压缩包注释
DeleteFile()删除整个 zip 文件
blob ReadFile(string file)工具函数:读文件为 blob
boolean WriteFile(blob data, string file)工具函数:把 blob 写成文件


最关键的一点Add* 之后必须调用 Close() 才会真正生成文件;中途想放弃调用 Discard()。这和数据库的事务提交/回滚是一个道理。

三、uo_zip 压缩:把目录和文件打进 ZIP
前置:工程已加入 websuite.pbl 并随应用分发 PbIdea.dll;下面代码放在某个按钮的 clicked 事件里,把路径换成你本机真实存在的目录/文件即可直接运行。
  1. // 示例输入:要生成的 zip 文件完整路径(不存在会被创建)
  2. string ls_zip
  3. ls_zip = 'D:/temp/demo.zip'
  4. // 示例输入:要加入压缩包的单文件完整路径
  5. string ls_file
  6. ls_file = 'D:/temp/report.txt'
  7. // 示例输入:要整目录打包的源目录(含子目录一并保留)
  8. string ls_srcdir
  9. ls_srcdir = 'D:/temp/sourcedir'
  10. uo_zip lz
  11. lz = create uo_zip
  12. // 打开压缩包(无密码);返回 true 表示打开成功
  13. boolean lb_open
  14. lb_open = lz.Open(ls_zip)
  15. // 加入单个文件
  16. lz.Add(ls_file)
  17. // 加入整个目录,目录结构会被保留进压缩包
  18. lz.AddPath(ls_srcdir)
  19. // 只有 Close 才真正把数据写入磁盘(相当于 commit)
  20. lz.Close()
  21. destroy lz
  22. MessageBox('压缩完成', '已生成:' + ls_zip)
复制代码

如果要做加密 zip,把 Open 换成带密码的重载即可:
  1. // 示例输入:zip 输出路径
  2. string ls_zip
  3. ls_zip = 'D:/temp/secret.zip'
  4. // 示例输入:压缩密码
  5. string ls_pwd
  6. ls_pwd = 'MyPass123'
  7. uo_zip lz
  8. lz = create uo_zip
  9. // bReadOnly=false 表示创建;第三个参数传密码即生成加密包
  10. lz.Open(ls_zip, false, ls_pwd)
  11. lz.Add('D:/temp/report.txt')
  12. lz.Close()
  13. destroy lz
  14. MessageBox('加密压缩完成', ls_zip)
复制代码

四、uo_zip 实战:解压与读取条目
前置:目标 zip 已存在(上面生成的 D:/temp/demo.zip),运行下面代码即可解压到指定目录。
  1. // 示例输入:要解压的 zip 文件
  2. string ls_zip
  3. ls_zip = 'D:/temp/demo.zip'
  4. // 示例输入:解压目标目录(不存在会自动创建)
  5. string ls_out
  6. ls_out = 'D:/temp/extract'
  7. uo_zip lz
  8. lz = create uo_zip
  9. lz.Open(ls_zip)
  10. // 解压全部条目到目标目录,返回解压出的条目数
  11. long ll_n
  12. ll_n = lz.Extract(ls_out)
  13. lz.Close()
  14. destroy lz
  15. MessageBox('解压完成', '共解压 ' + string(ll_n) + ' 个条目')
复制代码

读加密包时,Open 用只读 + 密码重载:lz.Open(ls_zip, true, ls_pwd)

读取条目清单(不解压也能知道里面有什么):
  1. // 示例输入:要查看的 zip 文件
  2. string ls_zip
  3. ls_zip = 'D:/temp/demo.zip'
  4. uo_zip lz
  5. lz = create uo_zip
  6. lz.Open(ls_zip)
  7. // GetEntryList 通过 ref 数组回填:索引/名称/原始大小/压缩后大小/CRC/时间/是否加密
  8. long ll_index[]
  9. string ls_name[]
  10. long ll_size[]
  11. long ll_sizecom[]
  12. string ls_crc[]
  13. string ls_dt[]
  14. boolean lb_enc[]
  15. long ll_cnt
  16. ll_cnt = lz.GetEntryList(ll_index, ls_name, ll_size, ll_sizecom, ls_crc, ls_dt, lb_enc)
  17. lz.Close()
  18. destroy lz
  19. MessageBox('条目数', string(ll_cnt))
复制代码

只读取某个条目内容为 blob(常用于"从压缩包里取一张图/一份配置,不落盘"):
  1. // 示例输入:zip 内要读取的条目名
  2. string ls_name
  3. ls_name = 'report.txt'
  4. // 示例输入:zip 文件
  5. string ls_zip
  6. ls_zip = 'D:/temp/demo.zip'
  7. uo_zip lz
  8. lz = create uo_zip
  9. lz.Open(ls_zip)
  10. // 按名称读取为 blob;也可按索引:lz.ReadBlob(1)
  11. blob lb_data
  12. lb_data = lz.ReadBlob(ls_name)
  13. lz.Close()
  14. destroy lz
  15. MessageBox('读到的字节数', string(len(lb_data)))
复制代码

五、uo_zip 内存压缩:不落盘,直接打包 blob

有时根本没有物理文件——比如你在内存里拼好了一段 JSON、一段日志,想直接压成 zip 再通过网络发出去。用 Add(string 名称, blob 数据) 即可,无需任何物理文件:
  1. // 示例输入:要打包进 zip 的文本内容
  2. string ls_text
  3. ls_text = 'Hello PBIDEA,这是内存压缩示例'
  4. // 示例输入:zip 输出文件
  5. string ls_zip
  6. ls_zip = 'D:/temp/mem.zip'
  7. uo_zip lz
  8. lz = create uo_zip
  9. lz.Open(ls_zip)
  10. // 把字符串转 blob 后作为条目加入(条目名自定义为 memo.txt)
  11. blob lb_blob
  12. lb_blob = blob(ls_text)
  13. lz.Add('memo.txt', lb_blob)
  14. lz.Close()
  15. destroy lz
  16. MessageBox('内存压缩完成', ls_zip)
复制代码

注意:blob(字符串) 按默认编码转换,若内容含中文且需 UTF-8,请先用 toUtf8(全局函数)转好再 blob()

六、uo_7z 完整 API 清单

uo_7z 对外方法(均来自 PbIdea.dllSevenZip* 系列):

方法说明
boolean AddDir(string strDir)加入整个目录(默认含子目录)
boolean AddDir(string, boolean includeSubDir)是否含子目录
boolean AddDir(string, string strFilter, boolean includeSubDir)指定文件过滤(如 *.txt
boolean AddFile(string fileName)加入单个文件
boolean Compress(string str7zFile)开始压缩成 .7z
boolean Compress(string str7zFile, boolean showProgress)压缩并显示进度条
boolean Extract(string str7zFile, string strDir)解压到目录
boolean Extract(string str7zFile, string strDir, boolean showProgress)解压并显示进度条
blob Compress7Z(blob data)内存 7z 压缩(自定义格式)
blob Uncompress7Z(blob data)内存 7z 解压(须配对使用)


和 uo_zip 不同,uo_7z 没有显式的 Open/Close:先 AddDir / AddFile 累加内容,再 Compress 一次性产出;解压则直接 Extract(源文件, 目标目录)

七、uo_7z 压缩目录/文件为 .7z
前置:同前,把路径换成你本机真实目录即可运行。
  1. // 示例输入:要生成的 7z 文件
  2. string ls_7z
  3. ls_7z = 'D:/temp/demo.7z'
  4. // 示例输入:要压缩的目录(含子目录)
  5. string ls_dir
  6. ls_dir = 'D:/temp/sourcedir'
  7. // 示例输入:是否弹出进度条
  8. boolean lb_progress
  9. lb_progress = false
  10. uo_7z l7
  11. l7 = create uo_7z
  12. // 加入整个目录(含子目录)
  13. l7.AddDir(ls_dir)
  14. // 也可追加单个文件:l7.AddFile('D:/temp/a.txt')
  15. // 仅压特定类型:l7.AddDir(ls_dir, '*.txt', true)
  16. boolean lb_ok
  17. lb_ok = l7.Compress(ls_7z, lb_progress)
  18. destroy l7
  19. MessageBox('7z 压缩结果', string(lb_ok))
复制代码

八、uo_7z 解压 .7z
  1. // 示例输入:源 7z 文件
  2. string ls_7z
  3. ls_7z = 'D:/temp/demo.7z'
  4. // 示例输入:解压目标目录
  5. string ls_out
  6. ls_out = 'D:/temp/extract7z'
  7. uo_7z l7
  8. l7 = create uo_7z
  9. boolean lb_ok
  10. lb_ok = l7.Extract(ls_7z, ls_out)
  11. destroy l7
  12. MessageBox('7z 解压结果', string(lb_ok))
复制代码

九、uo_7z 内存 7z 压缩(blob,自定义格式)

Compress7Z / Uncompress7Z 走的是 7z 内核的自定义内存格式,适合把一段二进制数据压小后存库或走网络,但只能用 Uncompress7Z 还原,标准 7z 工具打不开这段 blob——这点务必记牢。
  1. // 示例输入:要压缩的二进制数据(这里用字符串转 blob 示意)
  2. blob lb_src
  3. lb_src = blob('PBIDEA 7z 内存压缩示例内容')
  4. // 若是读真实文件:lb_src = lz.ReadFile('D:/temp/big.dat')
  5. uo_7z l7
  6. l7 = create uo_7z
  7. // 压缩
  8. blob lb_cmp
  9. lb_cmp = l7.Compress7Z(lb_src)
  10. // 解压还原(必须配对使用)
  11. blob lb_dec
  12. lb_dec = l7.Uncompress7Z(lb_cmp)
  13. destroy l7
  14. MessageBox('压缩前后字节数', string(len(lb_src)) + ' -> ' + string(len(lb_cmp)))
复制代码

十、进阶:配合 uo_dir 做选择性遍历再压缩

uo_zip.AddPath 是"整目录无脑打包"。如果你想按条件挑选文件(比如只压最近修改的、或只压某扩展名),可以先用 uo_dir(它是 autoinstantiate,无需 create)枚举文件清单,再逐一对 uo_zipAdd 调用。
  1. // 示例输入:要遍历的目录
  2. string ls_dir
  3. ls_dir = 'D:/temp/sourcedir'
  4. // 示例输入:文件名过滤(* 表示全部)
  5. string ls_filter
  6. ls_filter = '*.txt'
  7. // 示例输入:zip 输出路径
  8. string ls_zip
  9. ls_zip = 'D:/temp/selected.zip'
  10. uo_dir ld
  11. // uo_dir 为 autoinstantiate,无需 create
  12. string ls_files[]
  13. long ll_cnt
  14. ll_cnt = ld.files(ls_dir, ls_filter, ls_files)
  15. uo_zip lz
  16. lz = create uo_zip
  17. lz.Open(ls_zip)
  18. long i
  19. for i = 1 to ll_cnt
  20.     // 对每个命中的文件加入压缩包(这里直接用其完整路径作为条目名)
  21.     lz.Add(ls_files[i])
  22. next
  23. lz.Close()
  24. destroy lz
  25. MessageBox('已挑选并压缩的文件数', string(ll_cnt))
复制代码

uo_dir 常用配套:md(dir) 建多级目录、exist(file) 判断存在、dirs(dir, ref) 列子目录、del(file) 删文件、GetSize(dir) 算目录大小,均可直接调用。

边界情况与常见坑


  • 忘了 Close() 导致文件没生成:uo_zip 的所有 Add* 都只是"暂存",只有 Close() 才真正写盘;出错想放弃用 Discard()。这是最高频的坑。
  • uo_zip / uo_7z 必须 create/destroy:两者 constructor/destructor 里分别调用了 zipCreate/zipDestroySevenZipCreate/SevenZipDestroy,不 create 会报空对象,不 destroy 会泄漏底层句柄。
  • 7z 内存压缩的 blob 不能用标准工具解Compress7Z 产出的是自定义格式,归档给别人的 7z 请用 Compress(文件) 走标准 .7z;内存 blob 仅限自己 Uncompress7Z 还原。
  • GetEntryList 的 ref 数组要预先声明:七个 ref 数组(index/name/size/sizecom/crc/dt/enc)都要先声明再传入,函数通过引用回填,返回值是条目总数。
  • 中文路径/密码:底层走系统 API,建议路径与密码尽量使用 ASCII;中文文件名一般可行,但跨机器交换时优先用英文文件名最稳妥。
  • Open(blob, 密码) 只读打开:这个重载只能读不能写,用来"从一段内存里的 zip 数据直接读取条目"很方便,但别指望再往里 Add。
  • PbIdea.dll 必须随应用分发:这两个对象都依赖 PbIdea.dll,开发机能跑不代表客户机能跑,部署时务必把 dll 一起带上。


ZIP 还是 7z?以及替代方案


  • 兼容性优先 → uo_zip(ZIP):ZIP 是事实标准,Windows 资源管理器、各类解压软件原生支持,客户拿到就能双击打开,适合对外分发的附件、更新包。
  • 压缩率优先 → uo_7z(7z):7z 对大量小文件、文本类数据通常压得更小,适合内部归档、备份传输;但对方需要 7-Zip 或支持 7z 的工具才能解。
  • 纯内存数据压小 → 两者都行:uo_zip 的 Add(名称, blob) + 不解压直接用 ReadBlob;uo_7z 的 Compress7Z/Uncompress7Z(注意自定义格式)。
  • 替代方案:若只要最简单且不想依赖 PbIdea.dll,可用 Run 调用系统/第三方的 7z.exetar.exe;但那样要处理命令行、等待进程、解析返回,远不如这两个对象来得干净、可控。PBIDEA 没有内置 rar 对象,需要 rar 格式时仍建议走外部 exe 或改用 zip/7z。


小结

在 PB 里做压缩解压,记住三件事就够用了:uo_zip 管 ZIP(Open→Add→Close 三段式,别忘了 Close)、uo_7z 管 7z(AddDir/AddFile→Compress,Extract 直接解)、两者都靠 PbIdea.dll 且都要 create/destroy。需要挑文件就用 uo_dir 先枚举再 Add。把这几段代码收进你的工具库,以后导出、归档、打包上传都能直接复用。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-8-27 14:46 , Processed in 0.020347 second(s), 8 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表