专栏首页前端全栈开发者【快速复习】Node.js中的fs模块的使用

【快速复习】Node.js中的fs模块的使用

JavaScript 的是没有操作文件的能力,但是 Node 是可以做到的,Node 提供了操作文件系统模块,是 Node 中使用非常重要和高频的模块,是绝对要掌握的一个模块系统。

fs 模块提供了非常多的接口,这里主要说一下一些常用的接口。

1.常用API快速复习

fs.stat 检测是文件还是目录

const fs = require('fs')
fs.stat('hello.js', (error,stats)=>{
    if(error) {
        console.log(error)
    } else {
        console.log(stats)
        console.log(`文件:${stats.isFile()}`)
        console.log(`目录:${stats.isDirectory()}`)
    }
})

fs.mkdir 创建目录

onst fs = require('fs')
fs.mkdir('logs', error => {
    if(error) {
        console.log(error)
    } else {
        console.log('目录创建成功!')
    }
})

fs.rmdir 删除目录

const fs = require('fs')
fs.rmdir('logs', error => {
    if(error) {
        console.log(error)
    } else {
        console.log('成功删除了目录 logs')
    }
})

fs.writeFile 创建写入文件

const fs = require('fs')
fs.writeFile('logs/hello.log','您好~\n', error => {
    if(error) {
        console.log(error)
    } else {
        console.log('成功写入文件');
    }
})

fs.appendFile 追加文件

const fs = require('fs')
fs.appendFile('logs/hello.log','hello~\n', error => {
    if(error) {
        console.log(error)
    } else {
        console.log('成功写入文件');
    }
})

fs.readFile 读取文件

const fs = require('fs')
fs.readFile('logs/hello.log','utf-8', (error, data) => {
    if(error) {
        console.log(error)
    } else {
        console.log(data);
    }
})
const fs = require('fs')
fs.unlink(`logs/${file}`, error => {
    if(error) {
        console.log(error)
    } else {
        console.log(`成功删除了文件: ${file}`)
    }
})

fs.readdir 读取目录

const fs = require('fs')
fs.readdir('logs', (error, files) => {
    if(error) {
        console.log(error)
    } else {
        console.log(files);
    }
})

fs.rename 重命名,还可以更改文件的存放路径

const fs = require('fs')
fs.rename('js/hello.log', 'js/greeting.log', error => {
    if(error) {
        console.log(error)
    } else {
        console.log('重命名成功')
    }
})

2.第三方NPM包 mkdirp 的使用

mkdirp 不仅可以创建文件夹,还可以创建多层的文件夹,类似 mkdir -p 命令

	
midir -p tmp/foo/bar/baz

上述命令也可以在当前目录创建多层几文件夹。

如下代码在当前目录生成多层级文件夹

const mkdirp = require('mkdirp')
mkdirp('tmp/foo/bar/baz').then(made => console.log(`创建目录于: ${made}`))
// 创建目录于: /Users/zhangbing/github/CodeTest/Node/fs/tmp

结果

3.实战举例

实战1

判断服务器上面有没有 upload 目录。如果没有就创建这个目录,如果有的话不做操作

const fs = require('fs')
const path = './upload'
fs.stat(path, (err, data) => {
    if(err) {
        // 执行创建目录
        mkdir(path)
        return
    }
    if(data.isDirectory()) {
        console.log('upload目录存在');
    }else{
        // 首先删除文件,再去执行创建目录
        fs.unlink(path, err => {
            if(!err) {
                mkdir(path)
            }
        })
    }
})
function mkdir(dir) {
    fs.mkdir(dir, err => {
        if(err) {
            console.log(err);
            return
        }
    })
}

实战2

wwwroot 文件夹下面有 images css js 以及 index.html, 找出 wwwroot 目录下面的所有的目录,然后放在一个数组中

使用同步方法方式

const fs = require('fs')
const path = './wwwroot'
const dirArr = []
const dirs = fs.readdirSync(path)
dirs.forEach(item => {
    if(fs.statSync(path + '/' + item).isDirectory()) {
        dirArr.push(item)
    }
})
console.log('dirArr', dirArr)
// dirArr [ 'css', 'images', 'js' ]

使用 async/await 方式

const fs = require('fs')
const path = './wwwroot'
const dirArr = []
function isDir(path) {
    return new Promise((resolve, reject) => {
        fs.stat(path, (error, stats) => {
            if(error) {
                console.log(error)
                reject(error)
                return
            }
            if(stats.isDirectory()) {
                resolve(true)
            } else {
                resolve(false)
            }
        })
    })
}
function main(){
    fs.readdir(path, async (error, data) => {
        if(error) {
            console.log(error)
            return
        } else {
            for(let i = 0; i < data.length; i++) {
                if(await isDir(path + '/' + data[i])) {
                    dirArr.push(data[i])
                }
            }
            console.log('dirArr', dirArr)
        }
    })
}
main() // dirArr [ 'css', 'images', 'js' ]

4.管道流

管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。以下实例我们通过读取一个文件内容并将内容写入到另外一个文件中。

const fs = require("fs")
//创建一个可读流
const readerStream = fs.createReadStream('input.txt')
//创建一个可写流
const writerStream = fs.createWriteStream('output.txt')
//管道读写操作
//读取input.txt文件内容,并将内容写入到output.txt文件中
readerStream.pipe(writerStream)
console.log("程序执行完毕")

fs.createReadStream 从文件流中读取数据

onst fs = require('fs')
const fileReadStream = fs.fileReadStream('demo1.js')
let count = 0
let str = ''
fileReadStream.on('data', chunk => {
    console.log(`${++count}接收到:${chunk.length}`)
    str += chunk
})
fileReadStream.on('end', () => {
    console.log('---结束---')
    console.log(count + ',' + star)
})
fileReadStream.on('error', error => {
    console.log(error)
})

fs.createWriteStream 写入文件

const fs = require("fs")
const data ='我是从数据库获取的数据,我要保存起来'
//创建一个可以写入的流,写入到文件output.txt中
const writerStream = fs.createWriteStream('output.txt')
//使用utf8编码写入数据
writerStream.write(data,'UTF8')
//标记文件末尾
writerStream.end()
//处理流事件-->finish事件
writerStream.on('finish', () => {
    /*finish-所有数据已被写入到底层系统时触发。*/
    console.log("写入完成。")
})
writerStream.on('error', err => {
    console.log(err.stack);
})
console.log("程序执行完毕")

实战:复制图片

在项目根目录有一张图片2020.png,把它复制到 /wwwroot/images

代码如下

const fs = require("fs")
const readStream = fs.createReadStream('./2020.png')
const writeStream = fs.createWriteStream('./wwwroot/images/2021.png')
readStream.pipe(writeStream)

需要特别注意的是,fs.createWriteStream 要写入的目录一定要带上要复制的文件名,也就是不能写成 fs.createWriteStream('./wwwroot/images/') 否则在 macOS 下会报如下错误:

Error: EISDIR: illegal operation on a directory, open <directory>

本文源码:https://github.com/dunizb/CodeTest/tree/master/Node/fs

本文首发于博客:https://blog.zhangbing.site/2020/03/04/nodejs-fs-quick/

如果对你有一点点帮助,可以点个关注。

作者简介:做工程不做码农(微信公众号同名),Web前端工程师,坐标杭州,聚焦大前端技术的公众号,分享我的原创或精选文章,欢迎关注。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【译】7个简单但棘手的JavaScript面试问题

    如果您符合高级开发人员的资格,其工作涉及JavaScript,那么在编码面试中很有可能会被问到棘手的问题。

    Dunizb
  • 详解Webpack的loader和plugin编写

    loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中。

    Dunizb
  • 面试:Vue.js嵌套组件生命周期执行顺序是什么?

    有组件A,组件B,组件C,组件C是组件B的子组件,组件B又是组件A的子组件,那么直观的层级结构如下:

    Dunizb
  • echarts 使用心得

    echarts 是使用canvas绘图的,所以放置在背景容器的css背景图片不会被显示出来,所以如果需要显示背景图片。可以使用{backgroundColor:...

    frontoldman
  • 7.Android-压力测试、单元测试、日志猫使用

    表示测试com.example.phonecall应用程序,随机发送点击/滑动/切换事件10000次,( -v -v -v)表示信息日志为最高级,然后打印的信息...

    张诺谦
  • 优化强化学习Q-learning算法进行股市交易(附代码)

    地址:https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf

    量化投资与机器学习微信公众号
  • Java集合框架详解(全)

    集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurren...

    硕人其颀
  • 原创 Spring Boot 2.3 新特性分层JAR

    在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况

    冷冷
  • Python - 错误和异常

    描述:异常一般在ide无法直接检测出来,在我们执行到代码语句时,若有异常则会自动抛出

    小菠萝测试笔记
  • go语言实现设计模式(一):策略模式

    策略模式定义了算法家族,在调用算法家族的时候不感知算法的变化,客户也不会受到影响。

    超级大猪

扫码关注云+社区

领取腾讯云代金券