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 文件的压缩和解压。它不依赖于任何原生代码,易于安装和使用。

pnpm add adm-zip

并编写以下代码:

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 文件之前灵活地添加或修改内容。

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

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

向压缩文件中添加新内容

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

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 文件。

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

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

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

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

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 文件。

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

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

如何对压缩文件进行解压

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

const AdmZip = require("adm-zip");

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

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

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

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

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

加密压缩

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

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

brew install p7zip

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

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 文件的路径和要压缩的文件或文件夹的路径。这两个占位符会被相应的变量值替换。

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

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

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

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

对加密文件进行解压

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

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. -ppassword:提供用于解压的密码,{password}:提供用于解压的密码,{password}会被替换为之前定义的密码变量的值。

  4. -o”outputDir:指定解压缩的输出目录,{outputDir}”:指定解压缩的输出目录,{outputDir}是目标目录路径的变量。注意:路径如果包含空格,应该用引号””包围起来。

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

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

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

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

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

总结

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

原文链接:https://juejin.cn/post/7345025297139433482 作者:Moment

(0)
上一篇 2024年3月12日 上午10:06
下一篇 2024年3月12日 上午10:17

相关推荐

发表回复

登录后才能评论