前言
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作 API。 Node 导入文件系统模块fs全称File System,专门用来操作系统中的文件,常用的操作方式是对文件的读取和写入。
Node.js 文件系统(fs 模块)模块中的方法分成两类,一类是同步,另一类是异步,例如读取文件内容的函数有异步的 fs.readFile() (其中回调函数是异步方法) 和同步的fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。最好使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞(重点)。对于流量较大的服务器,最好还是采用异步操作,同步操作时,只有前一个操作结束,才会开始后一个操作,如果某个操作特别耗时(常常发生在读写数据时),会导致整个程序停顿
在上面我们说过来,fs模块里面的方法是分成同步和异步两类的,接下来我们将会成对(同步和异步方法)的简绍fs模块里面的常用方法
我们想在node.js 当中使用fs模块,那么我们首先要通过require的方式来引入fs模块
// 我们通过require(模块名称)函数执行就可以引入node的核心模块
const fs = require('fs') // 引入fs模块(他是一个对象)
fs.readFile异步读取文件
我们在读取文件的时候,可以读取任意类型的文件 如.js .html .css .png .exe等文件
fs.readFile(读取文件的路径,回调函数(读取错误的参数,读取成功的参数)) 异步读取文件
fs模块当中的一些异步的方法当中的回调函数里面的第一个参数一定是错误的参数(这就叫做错误优先)
const fs = require('fs')
fs.readFile('./demo.js', function (err, data) {
// data.toString()将Buffer转换成我们文件当中的内容(他是一个字符串)
console.log(err, data.toString());
})
fs.readFileSync同步读取文件
fs.readFileSync(要读取文件的路径) 同步读取文件
const fs = require('fs')
// 当前同步读取文件方法的返回值是当前你读取的数据
const data = fs.readFileSync('./demo.js')
// 他是一个buffer的格式,我们使用toString()转换成文本内容
console.log(data.toString());
在fs模块里面方法都是成对出现的
分别都是同步读取方式和异步读取方式
如readFile()内部的回调函数是异步读取方式,readFileSync同步读取方式
到现在我们可以发现异步方法是没有Sync的,而同步的方法是有Sync,这一点是很好记的能帮助提高记方法单词的效率。
为什么要使用buffer来表示我们读取的数据???
fs.readFile方法他的功能非常强大, 他不仅仅可以读取那些文本文件, 还可以读取图片(二进制图片)
所以说我们需要一种数据结构来表示这些文件(文件文件, 二进制文件) ,那这个数据结构是buffer格式的数据结构
但是我们使用fs.readFile的方式读取文件我们返回出来的数据,要使用toSting()方法显示的话,文本文件可以被显示,二进制文件是不不可以被显示的,但是都可以被写fs.writeFile
fs.readFile都可以读取文本文化和二进制文件(用buffer这种数据结果来表示读读取完成的数据)
文件的分类
总结(读取文件的方法)
读取文件(可以读取任意类型的文件 如.js .html .css等)
异步方法
fs.readFile(文件路径(相对/绝对路径),回调函数) 他内部的回调函数是一个异步的回调函数
回调函数 err 如果文件的路径不存在 则err就是一个错误对象
data 如果文件的路径存在 则data就是文件读取的数据 数据是buffer格式的
buffer格式(16进制)的数据可以使用toString()方法转成字符串
同步方法
const result = fs.readFileSync(文件的路径) 这函数是同步读取文件的方法
函数的返回值是读取文件的数据 同样返回值是一个buffer格式的数据可以使用toString()方法转成字符串
什么是Buffer???
Buffer是一种数据结构,专门用来存储二进制数据
Buffer上面的一些方法和属性
Buffer是node当中内置的一个类,其中Buffer.from函数执行可以传任何的数据,并且将传递的数据生成一个buffer的数据
// 现在转换出来的buffer数据就等于这个我们传递进去的数据
const buf = Buffer.from('巧克力很苦')
console.log(buf)
Buffer 中数据展示的形式都是16进制的,其中a的ASCII码是97,97的十六进制就是61
那么我们可以通过buffer.length的属性来获取到当前buffer数据的字节长度
// buffer.length 表示的是buffer的字节长度
const buffer = Buffer.from("巧克力很苦")
console.log(buffer.length)
这里要注意一下:Buffer数据的length表示buffer数据字节长度,跟字符串的length长度没有关系
那我们我们还可以用buffer.toString()的方法讲buffer的数据转换成我们可见的字符串(前提是文本文件)
// buffer.toString() 将文本文件的buffer数据转换成字符串
const buffer = Buffer.from("巧克力很苦")
console.log(buffer.toString())
fs.writeFile 异步创建写入文件
fs.writeFile(创建写入文件的名字, 写入创建文件的内容, 规定创建文件的编码格式, 回调函数(第一个参数是报错信息)) 异步创建写入文件
如果原本文件里面没有内容的话会写入,如果有内容的话就会覆盖
fs.writeFile('hello.txt', '写入文字', 'UTF-8', function(err){
console.log('写入成功')
})
我们使用fs.writeFile的方法是可以写文本文件,那么我们写二进制文件的时候我们需要使用fs.readFile方法读取文件,然后在使用fs.writeFile方法写出文件,案例如下
写图片
// 先读取图片的数据
fs.readFile('./1.png', function (err, data) {
// 在写入图片
fs.writeFile('./3.png', data, function (err) {
console.log(err);
})
})
写音频
// 先使用fs.readFile读取我们的音频数据
fs.readFile('./1.mp3', function (err,data) {
// 然后使用fs.writeFile写入我们的音频数据
fs.writeFile('./10.mp3', data, function (err) {
console.log(err);
})
})
写exe文件
// 使用fs.readFile 读取exe文件的数据
fs.readFile('./chrome.exe', function (err, data) {
// 然后使用fs.writeFile写入exe文件的数据
fs.writeFile('./谷歌.exe', data, function (err) {
console.log(err);
})
})
fs.writeFileSync 同步创建写入文件
fs.writeFileSync(创建写入文件的名字, 写入创建文件的内容, 规定创建文件的编码格式) 同步读取创建写入文件
const result = fs.readFileSync('./1.tet', '写入的文字', 'UTF-8')
console.log(result)
但是同步读取文件的方法不是很常用,因为我们无法预知我们读取的文件是不是有很大的体积的,如果有很大的体积那么就会造成主线程的堵塞,所以说我们一般建议用异步读取文件的方式
总结
写文件
fs.writeFile(文件的路径,数据,回调函数) 异步的方法
fs.writeFileSync(文件的路径,数据) 同步的方法
我们在写文件的时候 一般用异步方法
fs.unlink 异步删除文件
fs.unlink('要删除文件的路径', 回调函数(第一个参数是你的报错信息))
异步删除文件
fs.unlink('js/index.js', function(err) {
console.log('删除文件成功')
)
fs.unlinkSync 同步删除文件
fs.unlinkSync('要删除文件的路径')
同步删除文件
fs.unlinkSync('./10.txt')
如果你删除的文件很大的话有不想影响主线程的一些代码的话那么就使用异步的方法(fs.unlink),反之我们可以使用同步的方法(fs.unlinkSync)
fs.mkdir 异步创建文件夹
fs.mkdir(创建文件夹的路径, 回调函数(第一个参数是你的报错信息)) 异步创建文件夹
fs.mkdir('./文件夹2', function (err) {
console.log('文件夹创建成功', err)
})
fs.mkdirSync 同步创建文件夹
fs.mkdirSync(创建文件夹的路径)
fs.mkdirSync('./新的文件夹')
像这种创建文件夹的方法我们一般写成同步的方法
fs.rmdir 异步删除指定的文件夹
fs.rmdir('要删除文件夹的路径', 回调函数(第一个参数是你的报错信息))
异步删除目录(文件夹)
fs.rmdir('./文件夹', function (err) {
console.log('删除文件夹成功', err)
})
fs.rmdirSync 同步删除指定的文件夹
fs.rmdirSync(删除文件夹的路径) 同步删除指定的文件夹
fs.rmdirSync('./文件夹2')
如果我们要删除的文件夹是很大的单不想影响到主线程的代码,那么就使用异步的方法(fs.rmdir),反之使用同步的方法(fs.rmdirSync)
fs.readdir 异步读取(文件夹)的数据
fs.readdir(读取文件夹的名字, 回调函数(第一个参数是错误信息,第二个参数是你读取到了什么文件的数据))
异步读取(文件夹)的数据
fs.readdir('html', function (err, files) {
// 返回的是一个数组 数组每一项都是你被读取文件里面的内容
console.log(files, err)
})
readdirSync 同步读取(文件夹)的数据
fs.readdirSync(读取文件夹的名字) 同步
读取(文件夹)的数据
// 读取文件的数据,就是他的返回值
const result = fs.readdirSync('./新的文件夹')
console.log(result)
我们一般使用异步的方法来读取文件夹的路径(fs.readdir)
fs.stat 异步检测是文件还是目录
fs.stat(文件夹的路径,回调函数) 异步
检测是文件还是目录
回调函数第一个参数.isFile()
是否为文件
回调函数第一个参数.isDirectory()
是否为目录(文件夹)
// fs.stat(文件夹路径,回调函数) 检测是文件还是目录
// 可以直接带上后缀
fs.stat('index.html', function(err, stats){
// fn.stat 第二个参数 回调函数里面的第一个形参是报错信息 第二个形参是返回出来的结果
// stats.isFile 是否为文件
console.log("文件" + stats.isFile())
// state.isDirectory 是否为目录(文件夹)
console.log("文件夹" + stats.isDirectory())
})
fs.statSync 同步检测是文件还是目录
fs.
statSync(文件夹的路径) 同步
检测是文件还是目录
statSync的返回值.isFile()
是否为文件
statSync的返回值.isDirectory()
是否为目录(文件夹)
// 该放回值是存放了许多的方法和属性的
const stat = fs.statSync('./新的文件夹')
// 我们可以直接用.调用它
console.log(stat.isFile() , '文件')
console.log(stat.isDirectory() , '文件夹')
如果你要查看的文件过大的话有不想影响主线程的代码原型那么就使用异步方法(fs.stat),反之要使用同步方法(fs.statSync),一般建议的是使用同步的方法
fs.exists 异步查看某条路径是否存在
fs.exists(查看文件的路径, 回调函数(是否存在路径的一个布尔值)) 异步查看某条路径是否存在
fs.exists('./新的文件夹/1.js', function (bol) {
console.log(bol)
})
fs.existsSync 同步查看某条路径是否存在
fs.existsSync(查看文件的路径) 同步查看某条路径是否存在
// 他的返回值就是判断某条路径是否存在的布尔值
const bol = fs.existsSync('./新的文件夹/1.js')
console.log(bol)
exists方法以及废弃了那我们就是有existsSync方法把,最好是有同步方法查询(fs.existsSync)
改名字文件的名字
fs.rename 异步修改文件的名字
fs.rename
改名字(原本的文件内容是不会改变)
fs.rename('文件的路径(原始的名字)', '文件的路径(新的名字)', 回调函数(第一个参数是你的报错信息))
fs.rename('./html/sidebar.html','./html/header.html', function (err) {
console.log('修改名字成功')
})
fs.renameSync 同步修改文件的名字
fs.renameSync 改名字(原本的文件内容是不会改变的)
fs.renameSync('文件的路径(原始的名字)', '文件的路径(新的名字)')
fs.renameSync('./新的文件夹/10.js', './新的文件夹/1.js')
剪切
fs.rename 异步方法剪切
fs.rename(被剪切的文件的路径, 剪切到哪里文件的路径, 回调函数(第一个参数是你的报错信息))
fs.rename('./html/index.js', './js/index.js', function (err) {
console.log('剪切文件成功')
})
fs.renameSync 同步方法剪切
fs.rename(被剪切的文件的路径, 剪切到哪里文件的路径)
fs.rename('./html/index.js', './js/index.js')
剪切的时候同时要改名字
fs.rename 异步剪切的时候同时要改名字
fs.rename
剪切的时候同时有要改名字,fs.rename(要剪切文件的路径,要改名字的路径,回调函数)
fs.rename('./html/header.html', './js/abc.js', function (err) {
console.log('剪切文件成功')
})
fs.renameSync 同步剪切的时候同时要改名字
fs.renameSync
剪切的时候同时有要改名字,fs.rename(要剪切文件的路径,要改名字的路径)
fs.rename('./html/header.html', './js/abc.js')
fs.watchFile 异步观察文件的变化
fs.watchFile(要观察文件的路径, 监听的评率{} ,回调函数(改变后的文件状态,改变前的文件状态))
// 只要当前我们观察的文件的状态(更改文件的内容和修改文件名字)该变了,那么就会触发对应的回调函数
fs.watchFile('./10.txt', {interval:10} ,function (nextStat, preStat) {
// interval:毫秒数 表示你监听的频率
console.log(nextStat.size - preStat.size) // size是文件的体积
})
fs.appendFile 异步追加文件的内容
fs.appendFile(追加文件内容的文件名字, 追加文件内容, 回调函数(第一个参数是报错信息))异步
追加文件内容
// 追加内容多次是可以累加的 需要换行的话那么可以使他\n转义成回车
// 如果我需要追加的文件没有那么就会自动生成一个文件并且追加内容
// fs.appendFile 他包含 fs.writeFile
fs.appendFile('qkl.txt', '现在来追加文件内容\n000', function(err) {
console.log('写入成功')
})
fs.appendFileSync 同步追加文件的内容
fs.appendFile(追加文件内容的文件名字, 追加文件内容)异步
追加文件内容
fs.appendFile('qkl.txt', '现在来追加文件内容\n000')
在这里面我推荐使用异步的方法追加文件的内容(fs.appendFile)
最后
在这里面就向大家简绍了fs模块当中的一些方法,不过在fs模块 readFile writeFile rename 函数用的比较多,其他的方法大家知道认得就即可了
接下来的文字会写到,fs模块当中的流式读取,和静态文件托管,还有一些小练习