目录
fs 模块
在 Node.js 中,fs
模块是文件系统模块(File System module)的缩写,它提供了与文件系统进行交互的各种功能。通过 fs
模块,你可以执行诸如读取文件、写入文件、更改文件权限、创建目录等操作,Node.js 核心API之一
。
fs读取文件的三种策略
-
fs支持同步和异步两种模式 增加了
Sync
fs 就会采用同步的方式运行代码,会阻塞下面的代码,不加Sync就是异步的模式不会阻塞。 -
fs新增了promise版本,只需要在引入包后面增加/promise即可,fs便可支持promise回调。
-
使用可读流读取 使用场景适合读取
大文件
fs返回的是一个buffer二进制数据 每两个十六进制数字表示一个字节
案例:
1. 异步的方式,不会阻塞下面的代码
const fs = require('fs');
fs.readFile("./fsTest.txt",{
encoding: "utf8",
flag: "r"
},(err,data) => {
if(err) throw err;
console.log(data)
})
2. 同步的方式,加了encoding:utf8的话就是一个字符串,没有加的话就是一个buffer
const fs = require('fs');
const result = fs.readFileSync("./fsTest.txt",{
encoding: "utf-8",
flag: "r"
})
console.log(result)
console.log(1231)
3. 采用promise 的方式读取
const FILE_PATH = './fsTest.txt';
const FILE_ENCODING = 'utf8';
const fs = require('fs/promises');
fs.readFile(FILE_PATH,{encoding: FILE_ENCODING,flag: "r"})
.then((data) => {console.log(data)})
.catch((err) => {console.log(err)})
4. 采用可读流的方式读取,一点一点的读取,适合大文件
const FILE_PATH = './fsTest.txt';
const FILE_ENCODING = 'utf8';
let options= {
encoding: FILE_ENCODING,
flag: "r"
}
const fs = require('fs');
const fsStream = fs.createReadStream(FILE_PATH,options)
fsStream.on('data', (chunk) => {
console.log(chunk.toString());
})
fsStream.on('error', (err) => {
console.log(err);
})
对于option的介绍
读取文件 readFile 读一个参数 读取的路径, 第二个参数是个配置项
encoding 支持各种编码 utf-8之类的
flag
-
'a'
: 打开文件进行追加。 如果文件不存在,则创建该文件。 -
'ax'
: 类似于'a'
但如果路径存在则失败。 -
'a+'
: 打开文件进行读取和追加。 如果文件不存在,则创建该文件。 -
'ax+'
: 类似于'a+'
但如果路径存在则失败。 -
'as'
: 以同步模式打开文件进行追加。 如果文件不存在,则创建该文件。 -
'as+'
: 以同步模式打开文件进行读取和追加。 如果文件不存在,则创建该文件。 -
'r'
: 打开文件进行读取。 如果文件不存在,则会发生异常。 -
'r+'
: 打开文件进行读写。 如果文件不存在,则会发生异常。 -
'rs+'
: 以同步模式打开文件进行读写。 指示操作系统绕过本地文件系统缓存。 -
'w'
: 打开文件进行写入。 创建(如果它不存在)或截断(如果它存在)该文件。 -
'wx'
: 类似于'w'
但如果路径存在则失败。 -
'w+'
: 打开文件进行读写。 创建(如果它不存在)或截断(如果它存在)该文件。 -
'wx+'
: 类似于'w+'
但如果路径存在则失败。
fs其他的一些api
1. 创建文件夹
const fs = require('fs');
fs.mkdir("./path/view/add",{recursive: true},(err,data)=> {
if(err) throw err;
console.log(data)
})
{recursive: true} 设置后运行循环创建文件夹
2. 删除文件夹
const fs = require('fs');
fs.rm("./path",{recursive: true},(err)=> {
if(err) {
console.log(err);
} else {
console.log("path removed");
}
})
{recursive: true} 设置后会删掉指定目录的所有子目录
3. 重名文件
fs.renameSync("./oldData,json","./data.json")
4. 监听文件变化
监听文件的变化 返回监听的事件如change
,和监听的内容filename
const fs = require('fs');
fs.watch(FILE_PATH,(event,filename) => {
console.log(event,filename)
})
Event loop
const FILE_PATH = './fsTest.txt';
const FILE_ENCODING = 'utf8';
let options= {
encoding: FILE_ENCODING,
flag: "r"
}
const fs = require('fs');
fs.readFile(FILE_PATH,options,(err, data) => {
if (err) throw err;
console.log(data);
})
setTimeout(() => {
console.log("hello")
})
为什么先走setImmediate 呢,而不是fs
Node.js 读取文件的时候是使用libuv进行调度的
而setImmediate是由V8进行调度的
文件读取完成后 libuv 才会将 fs的结果 推入V8的队列
fs写入文件
- 第一个参数写入的文件
- 第二个参数写入的内容
- 第三个是options可选项 encoding编码 mode权限 flag
encoding和flag他们的参数与读取文件一致
fs.writeFile("index.txt","这是对于node.js文件模块的学习",{
encoding: FILE_ENCODING,
flag: "w"
},(err)=>{
console.log(err)
})
1. 追加写入
flag 换成a
或者使用
const fs = require('fs'); fs.appendFileSync("./index.txt","\n 这是追加")
2. 可写流
我们可以创建一个可写流 打开一个通道,可以一直写入数据,用于处理大量的数据写入,写入完成之后调用end 关闭可写流,监听finish 事件 写入完成
const FILE_PATH = './fsTest.txt';
const FILE_ENCODING = 'utf8';
let options= {
encoding: FILE_ENCODING,
flag: "r"
}
const fs = require('fs');
const data = fs.readFileSync(FILE_PATH,options)
let writeStream = fs.createWriteStream("./index.txt")
writeStream.write(data,FILE_ENCODING)
writeStream.end()
writeStream.on('finish',()=>{console.log("写入完成")})
3. 硬链接 和 软连接
硬链接的作用和用途如下:
- 文件共享:硬链接允许多个文件名指向同一个文件,这样可以在不同的位置使用不同的文件名引用相同的内容。这样的共享文件可以节省存储空间,并且在多个位置对文件的修改会反映在所有引用文件上。
- 文件备份:通过创建硬链接,可以在不复制文件的情况下创建文件的备份。如果原始文件发生更改,备份文件也会自动更新。这样可以节省磁盘空间,并确保备份文件与原始文件保持同步。
- 文件重命名:通过创建硬链接,可以为文件创建一个新的文件名,而无需复制或移动文件。这对于需要更改文件名但保持相同内容和属性的场景非常有用。
软链接的一些特点和用途如下:
- 软链接可以创建指向文件或目录的引用。这使得你可以在不复制或移动文件的情况下引用它们,并在不同位置使用不同的文件名访问相同的内容。
- 软链接可以用于创建快捷方式或别名,使得你可以通过一个简短或易记的路径来访问复杂或深层次的目录结构。
- 软链接可以用于解决文件或目录的位置变化问题。如果目标文件或目录被移动或重命名,只需更新软链接的目标路径即可,而不需要修改引用该文件或目录的其他代码。
就相当于Windows的快捷方式
用法:
fs.linkSync("./fsTest.txt", "./fsTest2.txt");
fs.symlinkSync("./index.txt", "./index2.txt","file", (err) => {
console.log(err)
});
注意:使用软连接时,在Windows系统上需要使用管理员权限
Crypto
实际开发中利用Node.js的crypto模块进行加密和验证操作。
1. 对称加密
对称加密是一种简单而快速的加密方式,它使用相同的密钥(称为对称密钥)来进行加密和解密。这意味着发送者和接收者在加密和解密过程中都使用相同的密钥。对称加密算法的加密速度很快,适合对大量数据进行加密和解密操作。然而,对称密钥的安全性是一个挑战,因为需要确保发送者和接收者都安全地共享密钥,否则有风险被未授权的人获取密钥并解密数据。
案例:
const crypto = require('crypto');
// 随机生成密钥和初始化向量
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
// 加密函数
function encrypt(text) {
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// 解密函数
function decrypt(text) {
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(text, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
let str = "我要被加密了!"
console.log("加密前:", str);
let encrypted = encrypt(str);
console.log("加密后:", encrypted);
let decrypted = decrypt(encrypted);
console.log("解密后:", decrypted);
2. 非对称加密
非对称加密使用一对密钥,分别是公钥和私钥。发送者使用接收者的公钥进行加密,而接收者使用自己的私钥进行解密。公钥可以自由分享给任何人,而私钥必须保密。非对称加密算法提供了更高的安全性,因为即使公钥泄露,只有持有私钥的接收者才能解密数据。然而,非对称加密算法的加密速度相对较慢,不适合加密大量数据。因此,在实际应用中,通常使用非对称加密来交换对称密
案例:
const crypto = require('crypto');
// 生成rsa钥匙对
const {publicKey, privateKey} = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
})
// 加密的内容
const content = 'hello world';
// 加密
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from(content));
console.log(encrypted.toString('hex'));
// 解密
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log(decrypted.toString());
3. 哈希函数
哈希函数具有以下特点:
- 固定长度输出:不论输入数据的大小,哈希函数的输出长度是固定的。例如,常见的哈希函数如 MD5 和 SHA-256 生成的哈希值长度分别为 128 位和 256 位。
- 不可逆性:哈希函数是单向的,意味着从哈希值推导出原始输入数据是非常困难的,几乎不可能。即使输入数据发生微小的变化,其哈希值也会完全不同。
- 唯一性:哈希函数应该具有较低的碰撞概率,即不同的输入数据生成相同的哈希值的可能性应该非常小。这有助于确保哈希值能够唯一地标识输入数据
使用场景
- 我们可以避免密码明文传输 使用md5加密或者sha256
- 验证文件完整性,读取文件内容生成md5 如果前端上传的md5和后端的读取文件内部的md5匹配说明文件是完整的
案例:
const crypto = require('crypto');
// hex加密需要的数据
const key = '12345678901234567890123456789012';
const data = `'1234567890'${key}`;
// hex加密
const hash = crypto.createHash('md5');
hash.update(data);
const hex = hash.digest('hex');
console.log(hex);