nodejs 学习笔记(三)—— fs模块&Stream
fs模块用来处理对文件的相关操作,常用的方法有:
fs.stat —— 检测是文件还是目录
fs.mkdir —— 创建目录
fs.writeFile —— 写入文件(没有会新建,有会覆盖原来的)
fs.appendFile —— 追加文件
fs.readFile —— 读取文件
fs.readdir —— 读取目录下所有文件和目录
fs.rename —— 重命名文件/目录(还可以用来移动文件/目录)
fs.rmdir —— 删除目录(目录要为空)
fs.unlink —— 删除文件
上面的这些方法大都是异步的,直接使用会遇到一些问题。比如这样一个例子:
读取 test 目录下的所有文件,放进一个数组里:
一般会想到要这样写:
const path = './test' let files = [] fs.readdir(path, (err, data) => { if (err) { console.log(err) return } for (var i = 0; i < data.length; i++) { fs.stat(path + '/' + data[i], (err, stats) => { if (err) { console.log(err) return } // 判断是不是文件,是文件放入数组中 if (stats.isFile()) { files.push(data[i]) } }) }
console.log(files) // []
})
因为 fs.stat() 方法是异步的,在判断是不是文件的时候 for 循环已经跑完了,每次 i 都是4,取不到文件,所以最后打印出来是空数组。
借助 ES6 的 Promise、 async、await 将代码改写如下就能够成功获取到所有文件。
const basePath = './test' let files = [] // 判断是否是文件 function isFile(path) { return new Promise((resolve, reject) => { fs.stat(basePath + '/' + path, (err, stats) => { if (err) { console.log(err) return } if (stats.isFile()) { resolve(true) } else { resolve(false) } }) }) } fs.readdir(basePath, async (err, data) => { if (err) { console.log(err) return } for (var i = 0; i < data.length; i++) { if (await isFile(data[i])) { files.push(data[i]) } } console.log(files) // [ 'aaa.js', 'bbb.html' ] })
Stream(流)
当文件较大时,可以采用以流的方式读取、写入文件
读取流:
var data = '' const stream = fs.createReadStream('./file.js') stream.on('data', function (chunk) { data += chunk }) stream.on('end', function () { console.log(data) // 打印出file.js里的内容 }) stream.on('error', function (err) { console.log(err) })
写入流:
// 写入流 const data = '写点东西进去' var stream = fs.createWriteStream('./writeSteam.js') stream.write(data, 'utf-8') stream.end() stream.on('finish', function () { console.log('写入完成') }) stream.on('error', function (err) { console.log(err) })
注意:用 nodemon 运行写入流代码会出现死循环,因为每次写入都发生修改,重新触发 nodemon 运行。
管道流:以流的形式读取、写入文件,可以用来实现大文件的复制
// 复制file.js到copy.js const readStream = fs.createReadStream('./file.js') const writeSteam = fs.createWriteStream('./copy.js') readStream.pipe(writeSteam)