Node.js精进(6)——文件
文件系统是一种用于向用户提供底层数据访问的机制,同时也是一套实现了数据的存储、分级组织、访问和获取等操作的抽象数据类型。
Node.js 中的fs模块就是对文件系统的封装,整合了一套标准 POSIX 文件 I/O 操作的集合,包括文件的读写、删除、遍历、重命名等操作。
fs 模块中的所有方法都提供了三种形式:回调、同步和 Promise ,其中 Promise 是在 Node.js 的版本 10 中引入的。
本系列所有的示例源码都已上传至Github,点击此处获取。
一、三种形式
在回调形式的方法中,最后一个参数是其回调函数,会异步地调用,其中回调函数的第一个参数始终为异常预留,不过有个例外是 exists() 方法。
回调形式不容易书写,很容易就会形成回调地狱。
虽然同步形式的方法比较容易书写,但是在执行时会阻止 Node.js 事件循环和阻塞 JavaScript 执行,直到操作完成。
Promise 形式的方法会使用底层的 Node.js 线程池,在事件循环线程之外异步地执行文件系统操作。对同一文件执行多个并发修改时必须小心,有可能会损坏数据。
以读取文件为例,三种形式的写法如下所示,若不指定编码,那么输出的将是 Buffer 实例。
const fs = require('fs');
// 回调
fs.readFile('./data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data); // strick
});
// 同步
const data = fs.readFileSync('./data.txt', 'utf8');
console.log(data); // strick
// Promise
const { promises } = fs;
async function readFilePromise() {
const data = await promises.readFile('./data.txt', 'utf8');
console.log(data); // strick
}
readFilePromise();
二、基础使用
1)判断文件是否存在
exists() 方法可用于判断文件是否存在,但在上一小节中曾提到,它已被弃用。
这是因为此回调的参数与其他回调不一致。通常,Node.js 回调的第一个参数是 err 参数,然后跟可选的其他参数,但 fs.exists() 回调只有一个布尔参数,如下所示。
fs.exists('./data.txt', isExist => {
console.log(isExist);
});
再则是因为 exists() 方法的功能用 access() 方法也能实现,其内部源码如下所示,其实也是调用了 access() 方法。
function exists(path, callback) {
maybeCallback(callback);
// 构造回调函数
function suppressedCallback(err) {
callback(err ? false : true);
}
try {
fs.access(path, F_OK, suppressedCallback);
} catch {
return callback(false);
}
}
其中 F_OK 是 fs 模块中的一个常量,表示文件是否存在,使用方法如下所示,R_OK 表示是否可读,W_OK 表示是否可写。
const { constants } = require('fs');
const { F_OK, R_OK, W_OK } = constants;
注意,在调用 fs.open()、fs.readFile() 或 fs.writeFile() 之前,不能使用 fs.access() 检查文件是否存在。
因为这样做会引入竞争条件,其他进程可能会在两次调用之间修改文件状态,造成非预期的结果。
遇到这种场景,推荐的做法是直接打开、读取或写入文件,当文件不可用时再做处理。
另一种判断文件是否存在的方法是调用 stat(),读取文件属性。
它有两个方法 isDirectory() 和 isFile() 可分别判断是否是目录和是否是文件,如下所示。
fs.stat('./data.txt', (err, stats) => {
console.log(stats.isDirectory());
console.log(stats.isFile());
});
同样要注意的是,它也不能在调用 fs.open()、fs.readFile() 或 fs.writeFile() 之前,检查文件是否存在。
2)方法
下面罗列的是 fs 模块的一些方法。
- fs.open():打开文件,可设置文件模式。
- fs.close():关闭文件描述符。
- fs.createReadStream():创建可读的文件流。
- fs.createWriteStream():创建可写的文件流。
- fs.readFile():读取文件的内容,相关方法:fs.read()。
- fs.writeFile():写入文件,相关方法:fs.write()。
- fs.link():新建指向文件的硬链接。
- fs.unlink():删除文件或符号链接。
- fs.mkdir():新建文件夹。
- fs.rmdir():删除文件夹。
- fs.readdir():读取目录的内容。
- fs.stat():读取文件属性,相关方法:fs.fstat()、fs.lstat()。
- fs.access():检查文件是否存在,以及 Node.js 是否有权限访问。
- fs.rename():重命名文件或文件夹。
- fs.appendFile():追加数据到文件,如果文件不存在,则创建文件。
- fs.copyFile():拷贝文件,可覆盖文件内容。
- fs.chmod():更改文件(通过传入的文件名指定)的权限,相关方法:fs.lchmod()、fs.fchmod()。
- fs.chown():更改文件(通过传入的文件名指定)的所有者和群组,相关方法:fs.fchown()、fs.lchown()。
- fs.watchFile():开始监控文件的更改,相关方法:fs.watch()。
- fs.unwatchFile():停止监控文件的更改。
3)路径
路径处理并不是在 fs 模块,而是在path模块,它的方法包括。
- path.basename():读取路径的最后一部分。
- path.dirname():读取路径的目录部分。
- path.extname():读取路径的文件扩展名。
- path.isAbsolute():判断是否是绝对路径。
- path.join():将多个部分合并成一个完整的路径。
- path.normalize():当包含类似 .、.. 或 // 等相对的说明符时,就尝试计算实际的路径。
- path.parse():解析成路径对象。
- path.relative():基于当前目录,返回从第一个路径到第二个路径的相对路径。
- path.resolve():将相对路径计算成绝对路径。
path.basename('../06/data.txt') // data.txt
path.dirname('../06/data.txt'); // ../06
path.extname('../06/data.txt'); // .txt
path.isAbsolute('../06/data.txt'); // false
path.join('../', '06', 'data.txt'); // ../06/data.txt
path.normalize('/../06/data.txt'); // /06/data.txt
// { root: '', dir: '../06', base: 'data.txt', ext: '.txt', name: 'data' }
path.parse('../06/data.txt');
path.relative('../', '../06/data.txt'); // 06/data.txt
path.resolve('../06/data.txt'); // /Users/code/web/node/06/data.txt
参考资料:
Node.js精进(6)——文件的更多相关文章
- 使用Node.JS监听文件夹变化
使用Node.JS监听文件夹改变有许多应用场合,比如: 构建自动编绎工具 当源文件改变时,自动运行build过程,比如当你写CoffeeScript文件或SASS CSS文件时,保存之后可即时生成对应 ...
- node.js编译less文件
大多数文章对于到底怎样编译less文件并没有一个详细的说明,清一色的grunt命令,看得也是晕晕的,所以也就有了这篇手记的存在. 步入正题 1.安装配置好sublime text3(包括各种实用插件) ...
- Node.js Express 路由文件分类
前言 基于上一篇Web Api Controller分类,在MVC中我们通常要按自己的业务来划分Controller层, 好处多多,那么Express框架作为Node.js的一款MVC框架,那么自然也 ...
- Node.js入门:文件查找机制
文件查找流程图 从文件模块缓存中加载 尽管原生模块与文件模块的优先级不同,但是都不会优先于从文件模块的缓存中加载已经存在的模块. 从原生模块加载 原生模块的优先级仅次于文件模块缓存的优 ...
- node.js监听文件变化
前言 随着前端技术的飞速发展,前端开发也从原始的刀耕火种,向着工程化效率化的方向发展.在各种开发框架之外,打包编译等技术也是层出不穷,开发体验也是越来越好.例如HMR,让我们的更新可以即时可见,告别了 ...
- node.js在读取文件时中文乱码问题
断更很久了........从今天开始会努力的持续更博,积极学习. 言归正传.今天在写node.js的demo时发现一个bug.我在node中读取本地的text文件时,发现英文的内容可以被读取,但是中文 ...
- Node + js实现大文件分片上传基本原理及实践(一)
_ 阅读目录 一:什么是分片上传? 二:理解Blob对象中的slice方法对文件进行分割及其他知识点 三. 使用 spark-md5 生成 md5文件 四. 使用koa+js实现大文件分片上传实践 回 ...
- Node.js精进(1)——模块化
模块化是一种将软件功能抽离成独立.可交互的软件设计技术,能促进大型应用程序和系统的构建. Node.js内置了两种模块系统,分别是默认的CommonJS模块和浏览器所支持的ECMAScript模块. ...
- Node.js精进(2)——异步编程
虽然 Node.js 是单线程的,但是在融合了libuv后,使其有能力非常简单地就构建出高性能和可扩展的网络应用程序. 下图是 Node.js 的简单架构图,基于 V8 和 libuv,其中 Node ...
随机推荐
- 什么?你们公司还没有将JVM初始和最大堆内存大小设置为相同值?
微信公众号:Java大家族 JVM将初始和最大内存大小设置为相同值的好处 启动应用程序时,我们指定初始内存大小和最大内存大小.对于在 JVM(Java 虚拟机)上运行的应用程序,初始和最大内存大小通过 ...
- 攻防世界-MISC:give_you_flag
这是攻防世界新手练习区的第四题,题目如下: 点击附件一下载,打开后发现是一个gif动图 可以看到动图有一瞬间出现了一个二维码,找一个网站给他分离一下 得到一张不完整的二维码(然后就不知道该怎么办了,菜 ...
- shiro550反序列学习
Shiro550 shiro550和fastjson作为攻防演练的利器,前面学习了fastjson的相关利用和回显,本篇主要来学习一下shiro550的漏洞原理. 1.漏洞原因 在 Shiro < ...
- Linux-SUID提权
前言 最近打靶场的时候最后都会涉及到提权,所以想着总结一下. SUID提权原理 SUID(设置用户ID)是赋予文件的一种权限,它会出现在文件拥有者权限的执行位上,具有这种权限的文件会在其执行时,使调用 ...
- [笔记] prufer 序列
什么是 prufer 序列 是可以和 \(n\) 个有标号节点的无根树一一对应的长度为 \(n-2\) 的序列. 一般来说是用于和树相关的组合计数问题,但是可能会出现一些变形,所以除了要了解一些性质, ...
- CentOS 8 重启不能DHCP获取IP的解决方法
一个执着于技术的公众号 今天遇到一个神奇的现象,我对CentOS 8系统做初始化之后再重启系统,发现系统不能通过NetworkManager获取DHCP IP了 查了系统日志发现是: Apr 30 0 ...
- SpringBoot从0到0.7——第一天
SpringBoot从0到0.7--第一天 学习的第一步当然是收拾好心情,先把环境搭建起来,写出第一个helloword出来. 第一步:安装IDEA和Tomcat 我安装的是IDEA 2021.2.2 ...
- Flutter网络请求和数据解析
一:前言 - 什么是反射机制,Flutter为什么禁用反射机制? 在Flutter中它的网络请求和数据解析稍微的比较麻烦一点,因为Flutter不支持反射机制.相信大家都看到这么一条,就是Flutte ...
- KLOOK客路旅行基于Apache Hudi的数据湖实践
1. 业务背景介绍 客路旅行(KLOOK)是一家专注于境外目的地旅游资源整合的在线旅行平台,提供景点门票.一日游.特色体验.当地交通与美食预订服务.覆盖全球100个国家及地区,支持12种语言和41种货 ...
- Go基础3:函数、结构体、方法、接口
目录 1. 函数 1.1 函数返回值 同一种类型返回值 带变量名的返回值 函数中的参数传递 函数变量 1.2 匿名函数--没有函数名字的函数 在定义时调用匿名函数 将匿名函数赋值给变量 匿名函数用作回 ...