windows上的压缩软件太傻逼?自己写一个吧 🤔🤔🤔

如果你对开源项目、提升技术、副业、面试、历史等等感兴趣的,可以加我微信 yunmz777,刚好我们有这样的交流群.

在 windows 系统上面,我们压缩文件,常常需要安装一些压缩软件才能实现压缩,可能有些还存在一些问题,例如 winrar 有广告,7z 界面好像比较古老。

那么接下来我们就来学习一下怎么自己实现一个压缩工具,彻底摆脱这些软件。

ZIP 压缩

ZIP 压缩是一种广泛使用的文件压缩格式,它通过减小文件大小来节省存储空间,同时便于文件的传输和分享。ZIP 文件不仅可以包含单个文件,还可以包含多个文件或文件夹,这些文件在压缩过程中会被合并成一个单一的文件,这样就方便了用户管理和传输。

ZIP 压缩算法主要利用了数据中的重复模式来减少文件的大小。当 ZIP 压缩软件发现数据中有重复的内容时,它会用更短的引用来替换这些重复内容,从而达到减少文件大小的目的。这个过程是可逆的,意味着压缩后的文件可以被解压缩回原来的状态,不会有任何数据丢失。

使用 ZIP 压缩的好处包括:

  1. 节省空间:ZIP 压缩可以显著减少文件的存储空间需求,特别是对于包含大量重复数据的文件。

  2. 便于传输:减小的文件大小意味着在网络上传输文件所需的时间更短,便于快速分享和下载。

  3. 整理文件:将多个文件和文件夹打包成单一的 ZIP 文件,可以简化文件管理和分发。

虽然 ZIP 是一种非常有效的压缩格式,但它并不总是能够提供最佳的压缩率。有些特定的压缩算法,比如 7-Zip 的 LZMA 算法,可能在某些情况下提供更好的压缩效率。因此,用户在压缩非常大的文件或需要极致压缩率的场合时,可能会考虑使用这些其他的压缩工具和格式。

实现文件夹压缩

我们最基础的功能就是需要把一个文件夹弄成一个压缩文件,最常见的场景就是微信传文件不能传文件,需要经过压缩:

要想使用,我们需要安装一个 adm-zip 包,它是一个用于 Node.js 的 JavaScript 实现,可以处理 ZIP 文件的压缩和解压。它不依赖于任何原生代码,易于安装和使用。

bash 复制代码
pnpm add adm-zip

并编写以下代码:

js 复制代码
const AdmZip = require("adm-zip");

const zip = new AdmZip();

// 添加整个目录到 ZIP 文件
zip.addLocalFolder("./article");

// 定义 ZIP 文件的保存路径
const outputPath = "./output.zip";

// 将 ZIP 文件保存到磁盘
zip.writeZip(outputPath, function (err) {
  if (err) {
    console.log("发生错误:", err);
  } else {
    console.log("ZIP 文件成功创建:", outputPath);
  }
});

ZIP 文件的创建和内容的添加是在内存中进行的,直到你调用 writeZip 或 toBuffer 等方法将 ZIP 数据实际写入到磁盘或其他存储介质之前,你是看不到任何新文件的。这种方式允许你在保存 ZIP 文件之前灵活地添加或修改内容。

最终输出效果正是我们想要的:

向压缩文件中添加新内容

接下来我们再看看新增内容的,我们首先编写如下代码:

js 复制代码
const AdmZip = require("adm-zip");

const zip = new AdmZip("./output.zip");

// 向ZIP文件中添加一个新文件,文件名为"newFile.txt",内容为"Hello World"
zip.addFile("moment.txt", Buffer.from("Hello World", "utf-8"));

// 保存更改,覆盖原有的ZIP文件
zip.writeZip("./output.zip");

console.log("新内容已添加到ZIP文件中。");

这段代码首先通过 Adm-Zip 加载一个已有的 ZIP 文件,然后使用 addFile 方法向其中添加一个新的文件。addFile 方法接受两个参数:第一个是要添加的文件名,第二个是文件的内容,以 Buffer 的形式提供。最后,调用 writeZip 方法将更改写回原文件或保存为一个新的 ZIP 文件。

最终输出结果如下图所示:

向压缩文件中删除指定内容

使用 Adm-Zip 删除 ZIP 文件中的内容也非常直接。我们可以使用 deleteFile 方法来删除 ZIP 文件中的指定文件。以下是如何使用 Adm-Zip 删除 ZIP 文件中特定内容的示例:

js 复制代码
const AdmZip = require("adm-zip");

const zip = new AdmZip("./output.zip");

zip.deleteFile("moment.txt");

zip.writeZip("./output.zip");

console.log("文件已从ZIP中删除。");

这段代码首先加载一个已有的 ZIP 文件,然后使用 deleteFile 方法删除指定的文件。这里,我们通过传递要删除的文件名作为参数来指定哪个文件应该被删除。最后,通过调用 writeZip 方法将更改写回原文件或保存为一个新的 ZIP 文件。

最终代码的输出结果如下图所示:

如何对压缩文件进行解压

使用 Adm-Zip 库在 Node.js 中解压 ZIP 文件同样简单直接。以下是步骤和代码示例,展示如何使用 Adm-Zip 解压 ZIP 文件:

js 复制代码
const AdmZip = require("adm-zip");

// 指定ZIP文件的路径
const zip = new AdmZip("./output.zip");

// 解压到指定的目录中,第二个参数为是否强制覆盖
zip.extractAllTo("./moment", true);

console.log("ZIP文件已成功解压。");

最终代码输出的结果如下图所示:

加密压缩

创建加密的 ZIP 文件在 Node.js 中稍微复杂一些,因为 Adm-Zip 不直接支持创建加密的 ZIP 文件。对于需要直接创建支持密码保护的 ZIP 文件的场景,可以考虑使用专门的命令行工具(如 7-Zip)通过 Node.js 的 child_process 模块调用。

在 mac 中,首先需要我们安装相对应的工具,如下:

bash 复制代码
brew install p7zip

安装完成之后,我们要在 node 中编写如下代码:

js 复制代码
const { exec } = require("child_process");

const password = "moment"; // 替换为你的密码
const inputFile = "./moment"; // 要加密的文件或文件夹路径
const encryptedZip = "./moment.zip"; // 输出的加密ZIP文件路径

const command = `7z a -p${password} -tzip -mem=AES256 ${encryptedZip} ${inputFile}`;

exec(command, (error, stdout, stderr) => {
  if (error) {
    console.error(`执行的错误: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  if (stderr) {
    console.error(`stderr: ${stderr}`);
  }
});

在上面的 command 中,定义了一个将要执行的命令字符串。命令使用了 7z(7-Zip 的命令行工具)来创建加密的 ZIP 文件。让我们分解这个命令:

  1. 7z:调用 7-Zip 命令行工具。

  2. a:表示添加文件到压缩文件中。

  3. -p${password}:设置密码用于加密压缩文件。${password}会被之前定义的 password 变量的值替换。

  4. -tzip:指定压缩文件的类型为 ZIP。

  5. -mem=AES256:指定使用 AES-256 加密算法进行加密。

  6. ${encryptedZip} ${inputFile}:分别是创建的加密 ZIP 文件的路径和要压缩的文件或文件夹的路径。这两个占位符会被相应的变量值替换。

上面代码的执行结果如下图所示:

被我们压缩成功了,且打开的时候需要密码的,输入密码后解压成功:

对加密文件进行解压

要使用 7z 命令实现 ZIP 文件的解压,特别是解压一个使用密码加密的 ZIP 文件,你可以在 Node.js 中使用类似的方法调用 7z 命令。

js 复制代码
const { exec } = require("child_process");

const password = "moment"; // 用于解压的密码,应与加密时相同
const zipFilePath = "./moment.zip"; // 加密的ZIP文件路径
const outputDir = "./777"; // 解压到的目录路径

const command = `7z x -p${password} -o"${outputDir}" "${zipFilePath}" -y`;

exec(command, (error, stdout, stderr) => {
  if (error) {
    console.error(`执行的错误: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  if (stderr) {
    console.error(`stderr: ${stderr}`);
  }
});

在上面的代码中,我们解释一下命令中的各个部分:

  1. 7z:调用 7-Zip 命令行工具。

  2. x:表示解压缩操作。

  3. -p <math xmlns="http://www.w3.org/1998/Math/MathML"> p a s s w o r d :提供用于解压的密码, {password}:提供用于解压的密码, </math>password:提供用于解压的密码,{password}会被替换为之前定义的密码变量的值。

  4. -o" <math xmlns="http://www.w3.org/1998/Math/MathML"> o u t p u t D i r " :指定解压缩的输出目录, {outputDir}":指定解压缩的输出目录, </math>outputDir":指定解压缩的输出目录,{outputDir}是目标目录路径的变量。注意:路径如果包含空格,应该用引号""包围起来。

  5. "${zipFilePath}":指向加密的 ZIP 文件的路径,如果路径包含空格,也应该用引号""包围。

  6. -y:自动回答所有提示为'是',例如覆盖现有文件的提示。

使用这个命令,你可以解压一个加密的 ZIP 文件到指定目录,不需要人工干预过程中的任何提示。

最终代码的允许结果如下图所示:

总结

通过上面的案例我们基本已经实现了一个压缩文件中的基本功能了,我们可以将这些思想使用 electron 或者 tauri 编写成一个桌面端,这样我们就不用去安装那些别人的软件了。

相关推荐
程序员爱钓鱼1 小时前
Go语言实战案例-创建模型并自动迁移
后端·google·go
javachen__1 小时前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
阿珊和她的猫3 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
uzong6 小时前
技术故障复盘模版
后端
GetcharZp7 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
加班是不可能的,除非双倍日工资7 小时前
css预编译器实现星空背景图
前端·css·vue3
桦说编程7 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研7 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi8 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip8 小时前
vite和webpack打包结构控制
前端·javascript