fs-extra替代 Node内置 fs 模块,更安全、更强大的文件操作库

fs-extra 是作为替代 Node.js 内置 fs 模块创建的,当你的项目中引入 fs-extra 后,就可以像下面这样做。将所有使用 require('fs') 的地方: 

const fs = require('fs') 
// this is no longer necessary

改成 require('fs-extra'):

const fs = require('fs-extra')

在 fs-extra 内部,除了重新导出(re-exporting)内置 fs 模块的所有方法外,还增加了一些常用而且安全的方法,比如 copy()、remove() 和 mkdirs()。

为什么?

按作者的原话说:“我已经厌倦了在我大多数项目里都引入一遍 mkdirp、rimraf 和 ncp”。

mkdirp、rimraf 和 ncp 是 3 个 npm 包,用来做不同类型的文件操作:

mkdirp:用来创建目录,支持嵌套嵌套目录的创建。实现类似 mkdir -p 指令的功能

rimraf:用来删除文件/目录,支持嵌套文件/目录的删除。实现 Linux 系统上 rm -rf 指令的功能

ncp:cp 就是 copy 简写,这个包用来复制文件/目录的,支持嵌套文件/目录的复制

之所以有这 3 个包出现,是因为 Node.js 内置 fs 模块实现上面 3 个功能有些麻烦,特别是嵌套文件/目录的复制和删除。

fs-extra 的做法

fs-extra 的作者将上面 3 个常用(创建目录、删除和复制)的功能统一在一个包中:

ensureDir(别名 mkdirs()、mkdirp()) 替代 mkdirp

remove 替代 rimraf

copy 替代 ncp

这些方法默认都是异步的,同步版本需要加上 Sycn 后缀,也就是:ensureDirSync、removeSync 和 copySync。

另外,还额外提供了其他的方法:

比如操作 JSON 文件读写的 writeJson 和 readJson 方法

比如清空目录 emptyDir 方法

fs-extra 额外提供的方法很多,我这里挑一些常用的方法做一下讲解。跟 fs 模块的内置方法异样,fs-extra 提供的 API 也会异步和同步版本,为了简单和方便,本文使用同步 API 做下实验。

准备工作

我们新建一个名为 fs-extra-demos 的项目,使用 pnpm 初始化后,在这里进行练习。

$ mkdir fs-extra-demos
$ cd fs-extra-demos
$ pnpm init
$ mkdir fs-extra-demos
$ cd fs-extra-demos
$ pnpm init

按照 fs-extra 依赖:

$ pnpm install fs-extra @types/fs-extra$ pnpm install fs-extra @types/fs-extra

package.json 启用 ES Module。

{  "type": "module", }

在实际练习时,我们经常会用到 __dirname,但 ES Module 并未提供,下面是获取方式:

import path from 'node:path'
import { fileURLToPath } from 'node:url'const __dirname = path.dirname(fileURLToPath(import.meta.url))

练习使用

copySync(src, dest[, options])

用于复制文件或者目录,支持嵌套目录下的复制。

一、如果 src 地址文件不存在会报错

import path from 'node:path'
import { copySync} from 'fs-extra/esm'// hello 文件不存在的情况下
copySync(path.resolve(__dirname, 'hello'))// Error: ENOENT: no such file or directory


二、当 src 地址存在,但 dest 参数(也就是目标地址)没赋值时会报错

// hello 文件存在的情况下
copySync(path.resolve(__dirname, 'hello'))// TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL.


三、复制文件

copySync(path.resolve(__dirname, 'hello'), path.resolve(__dirname, 'hello2'))// 成功!创建出 hello2


四、复制目录

// 已存在文件 hi/t.txt
copySync(path.resolve(__dirname, 'hi'), path.resolve(__dirname, 'hi2'))// 成功!复制出 hello2


再次执行也不会报错,同名文件会被复制过来的文件覆盖。

五、复制目录(设置不覆盖文件,出现同名文件时报错)


copySync(path.resolve(__dirname, 'hi'), path.resolve(__dirname, 'hi2'), { overwrite: false, errorOnExist: true })// Error: 'D:\fe-projects\fs-extra-demos\copySync\hi2\t.txt' already exists

这个很少使用。我们通常不希望意外的报错影响我们的代码流程。

六、复制目录的位置存在同名文件会报错

// 已存在文件 hi/t.txt,已存在文件 hi2
copySync(path.resolve(__dirname, 'hi'), path.resolve(__dirname, 'hi2'))// Error: Cannot overwrite non-directory 'D:\fe-projects\fs-extra-demos\copySync\hi2' with directory 'D:\fe-projects\fs-extra-demos\copySync\hi'.
同理,复制文件的位置存在同名目录也会报错。// 已存在文件 hi2, 已存在目录 hi3
copySync(path.resolve(__dirname, 'hi2'), path.resolve(__dirname, 'hi3'))// Error: Cannot overwrite directory 'D:\fe-projects\fs-extra-demos\copySync\hi3' with non-directory 'D:\fe-projects\fs-extra-demos\copySync\hi2'
当然,这种情况非常少见。记住一个原则就能避免这个错误,就能安全地使用 copySync 方法:在同一个目录结构下,不允许出现同名的目录或者文件。removeSync(path)

用于删除文件或者目录,支持嵌套目录下的删除。

一、删除文件不存在不会报错

import path from 'node:path'
import { removeSync } from 'fs-extra/esm'removeSync(path.resolve(__dirname, 'hello'))

二、删除文件或目录

// 已存在文件 hello,已存在文件 hi/t.txtremoveSync(path.resolve(__dirname, 'hello'))
removeSync(path.resolve(__dirname, 'hi'))// 成功!文件和目录都被删除
目录中即使有内容,也能完全删除,不会报错。总之,removeSync 方法使用起来非常安全,不会报错。ensureDirSync(dir[,options])
用于创建目录,支持嵌套目录的创建。还有 2 个别名:mkdirsSync、mkdirpSync。多个目录和多层嵌套目录都 OK。import path from 'node:path'
import { ensureDirSync } from 'fs-extra/esm'// 创建单层目录 & 多层目录
ensureDirSync(path.resolve(__dirname, 'hello'))
ensureDirSync(path.resolve(__dirname, 'world/x/xx'))
重复执行上述代码也不会报错。对于已存在的目录结构,ensureDirSync 方法什么都不做。ensureFileSync(file)跟ensureDirSync类似,ensureFileSync用于创建文件。

一、直接创建文件 & 创建嵌套在目录结构中的文件

import path from 'node:path'
import { ensureFileSync } from 'fs-extra/esm'// 直接创建文件 & 创建嵌套在目录结构中的文件
ensureFileSync(path.resolve(__dirname, 'hello.txt'))
ensureFileSync(path.resolve(__dirname, 'world/x/xx.txt'))
在创建嵌套在目录结构中的文件时,如果父级目录不存在,会自动创建。

重复执行上述代码也不会报错。对于已存在的文件,ensureFileSync 方法什么都不做。

二、在已存在文件的地方创建同名目录会报错

import path from 'node:path'
import { ensureDirSync } from 'fs-extra/esm'// 在已存在文件的地方创建同名目录会报错
ensureDirSync(path.resolve(__dirname, 'hello.txt'))
ensureDirSync(path.resolve(__dirname, 'world/x/xx.txt'))// Error: EEXIST: file already exists, mkdir 'D:\fe-projects\fs-extra-demos\ensureFileSync\hello.txt'
同理,在已存在目录的地方创建同名文件也会报错import path from 'node:path'
import { ensureDirSync } from 'fs-extra/esm'// 在已存在文件的地方创建同名目录会报错
ensureDirSync(path.resolve(__dirname, 'hello.txt'))
ensureDirSync(path.resolve(__dirname, 'world/x/xx.txt'))// Error: EEXIST: file already exists, mkdir 'D:\fe-projects\fs-extra-demos\ensureFileSync\hello.txt'
当然,上面两种情况很少遇到。还是那个原则:在同一个目录结构下,不允许出现同名的目录或者文件。emptyDirSync(dir)

用于清空目录。支持嵌套目录中的文件清除。

一、清空目录

import path from 'node:path'
import { emptyDirSync } from 'fs-extra/esm'
import { fileURLToPath } from 'node:url'const __dirname = path.dirname(fileURLToPath(import.meta.url))// 当前存在文件 you/t/tt/ttt.txt, me/t.txt
emptyDirSync(path.resolve(__dirname, 'you'))
emptyDirSync(path.resolve(__dirname, 'me'))// 成功清空目录 you & me


二、如果要清空的目录不存在,就会创建这个目录

// 当前没有目录 hi & hello
emptyDirSync(path.resolve(__dirname, 'hello'))
emptyDirSync(path.resolve(__dirname, 'hi'))// 成功创建目录 hi/ & hello/
emptyDirSync 方法也超好用,不会报错。readJsonSync(file[, options])

用于读取 JSON 文件。内部使用的是 jsonfile 包提供的方法。

一、读取不存在的文件会报错

import path from 'node:path'
import { readJsonSync } from 'fs-extra/esm'
import { fileURLToPath } from 'node:url'const __dirname = path.dirname(fileURLToPath(import.meta.url))console.log(readJsonSync(path.resolve(__dirname, 'hello.json'))
)
// Error: D:\fe-projects\fs-extra-demos\readJsonSync\hello.json: ENOENT: no such file or directory, open 'D:\fe-projects\fs-extra-demos\readJsonSync\hello.json'


二、会将读取到的文件内容转成 JS 对象

console.log(readJsonSync(path.resolve(__dirname, '../package.json'))
)
/*
{name: 'fs-extra-demos',version: '1.0.0',description: '',main: 'index.js',type: 'module',scripts: { test: 'echo "Error: no test specified" && exit 1' },keywords: [],author: '',license: 'ISC',dependencies: { '@types/fs-extra': '^11.0.1', 'fs-extra': '^11.1.1' }
} */

writeJsonSync(file, object[, options])
用于写 JSON 文件。跟 readJsonSync 方法一样,内部使用的是 jsonfile 包提供的方法。

import path from 'node:path'
import { writeJsonSync } from 'fs-extra/esm'
import { fileURLToPath } from 'node:url'const __dirname = path.dirname(fileURLToPath(import.meta.url))writeJsonSync(path.resolve(__dirname, 'hello.json'), { hello: 'world' })// 成功创建文件 hello.json

hello.json 文件内容:

{"hello":"world"}
(注意,有一个空行 EOF,这是默认行为)

当然我们也可以使用第 3 个参数做格式化:

writeJsonSync(path.resolve(__dirname, 'hello.json'), { hello: 'world' }, { spaces: 2, EOL: '\r\n' })
我们使用了 2 个空格的缩进,同时换行符采用 Windows 系统默认的 \r\n(writeJsonSync 方法默认是  \n,更好一些)hello.json 文件被覆盖为:{"hello": "world"
}

moveSync(src, dest[, options])

用于移动文件或者目录。

一、移动不存在的文件

import path from 'node:path'
import { moveSync } from 'fs-extra/esm'
import { fileURLToPath } from 'node:url'const __dirname = path.dirname(fileURLToPath(import.meta.url))moveSync(path.resolve(__dirname, 'hello'))// Error: ENOENT: no such file or directory, lstat 'D:\fe-projects\fs-extra-demos\moveSync\hello'


二、移动文件或者目录

// 已存在目录 hello/t/tt/ttt,已存在文件 world.txtmoveSync(path.resolve(__dirname, 'world.txt'), path.resolve(__dirname, 'world2.txt'))
moveSync(path.resolve(__dirname, 'hello'), path.resolve(__dirname, 'hello2'))// 移动后的结构
// world2.txt
// hello2/t/tt/ttt


三、移动目录的位置存在文件会报错

// hello2 是一个目录,world2.txt 是一个文件
moveSync(path.resolve(__dirname, 'hello2'), path.resolve(__dirname, 'world2.txt'))// Error: Cannot overwrite non-directory 'D:\fe-projects\fs-extra-demos\moveSync\world2.txt' with directory 'D:\fe-projects\fs-extra-demos\moveSync\hello2'.
同理,移动文件的位置存在目录也会报错// hello2 是一个目录,world2.txt 是一个文件
moveSync(path.resolve(__dirname, 'world2.txt'), path.resolve(__dirname, 'hello2'))// Error: Cannot overwrite directory 'D:\fe-projects\fs-extra-demos\moveSync\hello2' with non-directory 'D:\fe-projects\fs-extra-demos\moveSync\world2.txt'.

也就是说,移动的问题存在不同类型的文件,就会报错。

pathExistsSync

判断指定路径下的文件或者目录是否存在。其实就是 fs.existsSync() 方法的别名。

import path from 'node:path'
import { pathExistsSync } from 'fs-extra/esm'
import { fileURLToPath } from 'node:url'const __dirname = path.dirname(fileURLToPath(import.meta.url))console.log(pathExistsSync(path.resolve(__dirname, 'hello'))
)
// false// 创建 hello 目录或文件
console.log(pathExistsSync(path.resolve(__dirname, 'hello'))
)
// true

pathExistsSync 方法用起来也很安全,不会报错。

总结
总的来说,使用 fs-extra 还是很安全的,只要记住一个原则就好:在涉及写操作的时候,要确保写入的是同一个文件类型(文件写文件,目录写目录),否则会报错。

copySync:用于文件或目录的复制,只要保证复制的原文件存在就能安全使用

removeSync:用于删除文件或目录,可以安全使用,永远不会报错

ensureDirSync & ensureFileSync:分别用于目录和文件的创建,当目标位置如果有目录或文件存在时,什么都不会做,正如方法名所言,是用来“保证(ensure)”这个位置有目录或文件的

readJsonSync:读取 JSON 文件,只要保证复制的原文件存在就能安全使用

writeJsonSync:写 JSON 文件。可以使用第 3 个参数做写入 JSON 数据的格式化

moveSync:移动文件或目录,只要保证移动的原文件存在就能安全使用

pathExistsSync:判断文件或目录是否存在,可以安全使用,永远不会报错

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/671358.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

im即时通讯源码/仿微信app源码+php即时通讯源码带红包+客服+禁言等系统php+uniapp开发

即时通讯(IM)系统是现代互联网应用中不可或缺的一部分,它允许用户进行实时的文本、语音、视频交流。随着技术的发展,IM系统的功能越来越丰富,如红包、客服、禁言等。本文将探讨如何使用PHP语言开发一个功能完备的即时通讯系统,包括…

Java Set集合

1. Set接口 1.1 Set接口概述 Set接口继承自Collection接口,所以与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格。 Set集合的特点是无序且不可重复: 无序:不…

网卡自动切换AP和AC模式

AC模式搜索不到WiFi AC模式是指client模式,也就是可以自动接入wifi的模式 参考将外置网卡设置为 AP模式之后,发现搜索不到wifi了 (换了一台ubuntu测试发现可以,所以不是硬件问题) 经过nmcli device status查看设备发…

OCC笔记:图形可视化的实现方式

注:文中参看的occ的源码版本为7.4.0 1、实现思路概览 整体架构 主要有3大块:AIS(Application Interactive Services ,直译为:应用程序交互服务)、Graphics(图形)、Geometry & T…

2024.05.06作业

自由发挥应用场景,实现登录界面。 要求:尽量每行代码都有注释。 #include "yuanshen.h"yuanshen::yuanshen(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(1600,910);this->setFixedSize(1600,910);//窗口标题this-…

【C语言】数据类型

有哪些数据类型? char - 字符数据类型,存储一个字符,大小是1字节。short - 短整型,存储一个整数,大小是2字节。int - 整型,存储一个整数,大小是4字节。long - 长整型,存储一个整数&…

华为 二层交换机与防火墙连通上网实验

防火墙是一种网络安全设备,用于监控和控制网络流量。它可以帮助防止未经授权的访问,保护网络免受攻击和恶意软件感染。防火墙可以根据预定义的规则过滤流量,例如允许或阻止特定IP地址或端口的流量。它也可以检测和阻止恶意软件、病毒和其他威…

AIGC时代重塑数字安全风控体系

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

SpringSecurity6 学习

学习介绍 网上关于SpringSecurity的教程大部分都停留在6以前的版本 但是,SpringSecurity6.x版本后的内容进行大量的整改,网上的教程已经不能够满足 最新的版本使用。这里我查看了很多教程 发现一个宝藏课程,并且博主也出了一个关于SpringSec…

VBA编程之条件语句

上一篇我们讲述了条件语句以及分支。文章的最后用到了逻辑运算符“And“那么今天我们来聊一聊逻辑运算符和Select……Case结构。 在学习前我们先来了解一下,在生活中我们经常说”这个包括那个“,”你或者他“,”不是“等等。而这里”包括“和…

SX1308 高效率1.2MHz2A升压稳压器芯片IC

一般说明 该SX1308是一个恒定频率,6引脚SOT23电流模式升压转换器用于小型,低功耗应用。在1.2MHz的SX1308开关,并允许使用微小,低成本的电容器和电感器2毫米或更低的高度内部软启动小浪涌电流的结果,延长电池寿命…

CellMarker | 人骨骼肌组织细胞Marker大全!~(强烈建议火速收藏!)

1写在前面 分享一下最近看到的2篇paper关于骨骼肌组织的细胞Marker&#xff0c;绝对的Atlas级好东西。&#x1f44d; 希望做单细胞的小伙伴觉得有用哦。&#x1f60f; 2常用marker&#xff08;一&#xff09; general_mrkrs <- c( MYH7, TNNT1, TNNT3, MYH1, MYH2, "C…