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)
原文地址:https://www.cnblogs.com/zdd2017/p/14628721.html