golang 7zip dll
创建目录 zipdll
代码:
unzip.go
package main
/*
#include <stdlib.h>
// 定义回调类型
typedef void (*Callback)(const char*);
// 将 call_callback 声明为 static
static void call_callback(void (*cb)(const char*), const char* message) {
if (cb != NULL) {
cb(message);
}
}
*/
import "C"
import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/bodgit/sevenzip"
)
// 计算 7z 文件的总大小
func calculate7zTotalSize(reader *sevenzip.Reader) int64 {
var totalSize int64
for _, file := range reader.File {
totalSize += int64(file.UncompressedSize)
}
return totalSize
}
// 解压 7z 文件并调用回调
//export Unzip7zWithCallback
func Unzip7zWithCallback(archivePath *C.char, destDir *C.char, cb C.Callback) {
goArchivePath := C.GoString(archivePath)
goDestDir := C.GoString(destDir)
// 打开 7z 文件
file, err := os.Open(goArchivePath)
if err != nil {
C.call_callback(cb, C.CString("Failed to open 7z file"))
return
}
defer file.Close()
// 获取文件信息
fileInfo, err := file.Stat()
if err != nil {
C.call_callback(cb, C.CString("Failed to get file info"))
return
}
// 创建 7z 读取器
reader, err := sevenzip.NewReader(file, fileInfo.Size())
if err != nil {
C.call_callback(cb, C.CString("Failed to create 7z reader"))
return
}
// 计算总大小以跟踪进度
totalSize := calculate7zTotalSize(reader)
if totalSize == 0 {
C.call_callback(cb, C.CString("Empty 7z file"))
return
}
var processedSize int64
progressStep := totalSize / 200 // 0.5% 对应的字节数
nextProgressTrigger := progressStep
// 解压文件
for _, file := range reader.File {
path := filepath.Join(goDestDir, file.Name)
// 检查是否是目录
if file.FileHeader.FileInfo().IsDir() {
os.MkdirAll(path, 0755)
continue
}
// 创建解压目标文件
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
C.call_callback(cb, C.CString(fmt.Sprintf("Failed to create directory: %s", err.Error())))
return
}
destFile, err := os.Create(path)
if err != nil {
C.call_callback(cb, C.CString(fmt.Sprintf("Failed to create file: %s", err.Error())))
return
}
defer destFile.Close()
// 打开 7z 内部文件
rc, err := file.Open()
if err != nil {
C.call_callback(cb, C.CString(fmt.Sprintf("Failed to open entry in 7z: %s", err.Error())))
return
}
defer rc.Close()
// 复制文件并更新进度
buffer := make([]byte, 1024*64) // 每次读取 64KB
for {
n, err := rc.Read(buffer)
if err != nil && err != io.EOF {
C.call_callback(cb, C.CString(fmt.Sprintf("Failed to read file: %s", err.Error())))
return
}
if n == 0 {
break
}
if _, err := destFile.Write(buffer[:n]); err != nil {
C.call_callback(cb, C.CString(fmt.Sprintf("Failed to write file: %s", err.Error())))
return
}
// 更新处理的字节数
processedSize += int64(n)
// 每 0.5% 调用一次回调
if processedSize >= nextProgressTrigger {
progress := float64(processedSize) / float64(totalSize) * 100
C.call_callback(cb, C.CString(fmt.Sprintf("Progress: %.2f%%", progress)))
nextProgressTrigger += progressStep
}
}
}
C.call_callback(cb, C.CString("7z extraction completed successfully"))
}
func main() {}
目录下执行 go mod init
go mod tidy
编译:GOOS=windows GOARCH=amd64 go build -o unzip7z_64.dll -buildmode=c-shared unzip.go
GOOS=windows GOARCH=386 go build -o unzip7z_32.dll -buildmode=c-shared unzip.go