02-常用内置模块

内置模块path

  • path模块用于对路径和文件进行处理,提供了很多好用的方法。

  • 并且我们知道在Mac OS、Linux和window上的路径时不一样的

    • window上会使用 \或者 \ 来作为文件路径的分隔符,当然目前也支持 /
    • 在Mac OS、Linux的Unix操作系统上使用 / 来作为文件路径的分隔符
  • 可移植操作系统接口

    • Linux和Mac OS都实现了POSIX接口
    • Window部分电脑实现了POSIX接口

path常见的API

  • 从路径中获取信息

    • dirname:获取文件的父文件夹
    • basename:获取文件名;
    • extname:获取文件扩展名
  • 路径的拼接

    • 如果我们希望将多个路径进行拼接,但是不同的操作系统可能使用的是不同的分隔符
    • 这个时候我们可以使用path.join函数
  • 将文件和某个文件夹拼接

    • 如果我们希望将某个文件和文件夹拼接,可以使用 path.resolve
    • resolve函数会判断我们拼接的路径前面是否有 /或…/或./;
    • 如果有表示是一个绝对路径,会返回对应的拼接路径
    • 如果没有,那么会和当前执行文件所在的文件夹进行路径的拼接
const path = require('path')

const filePath = 'stu_node/learn_node/03_path/test.txt'

// 1.获取路径信息
console.log(path.dirname(filePath))  //stu_node/learn_node/03_path
console.log(path.basename(filePath)) //test.txt
console.log(path.extname(filePath))  //.txt

// 2.join路径拼接
const basePath = 'stu_node/learn_node/03_path'
const fileName = 'test.txt'
console.log(path.join(basePath, fileName)) //stu_node\learn_node\03_path\test.txt

// 3.resolve拼接,会判断路径中是否有./ ../
console.log(path.resolve(basePath, fileName)) //C:\Users\yihua\Desktop\code\stu_node\learn_node\03_path\stu_node\learn_node\03_path\test.txt

内置模块fs

借助于Node帮我们封装的文件系统,我们可以在任何的操作系统(window、Mac OS、Linux)上面直接去操作文件

API大多数都提供三种操作方式:
  • 同步操作文件:代码会被阻塞,不会继续执行;
  • 异步回调函数操作文件:代码不会被阻塞,需要传入回调函数,当获取到结果时,回调函数被执行
  • 异步Promise操作文件:代码不会被阻塞,通过 fs.promises 调用方法操作,会返回一个Promise,可以通过then、catch进行处理;
const fs = require('fs')

// 读取文件信息
const filePath = './abc.txt'
// 1.同步操作
const info = fs.statSync(filePath)
// 后续的代码会被阻塞
console.log(info)

// 2.异步操作,不阻塞
fs.stat(filePath,(err,info)=>{
  if(err){
    console.log(err);
  }else{
    console.log(info);
  }
})

// 3.promise,不阻塞
fs.promises.stat(filePath).then(info=>{
  console.log(info);
}).catch(err=>{
  console.log(err);
})
文件描述符

是什么?

  • 在 POSIX 系统上,对于每个进程,内核都维护着一张当前打开着的文件和资源的表格
  • 每个打开的文件都分配了一个称为文件描述符的简单的数字标识符
  • 在系统层,所有文件系统操作都使用这些文件描述符来标识和跟踪每个特定的文件。
  • Windows 系统使用了一个虽然不同但概念上类似的机制来跟踪资源

为了简化用户的工作,Node.js 抽象出操作系统之间的特定差异,并为所有打开的文件分配一个数字型的文件描述符

fs.open() 方法用于分配新的文件描述符

  • 一旦被分配,则文件描述符可用于从文件读取数据、向文件写入数据、或请求关于文件的信息
const fs = require('fs')

fs.open('./abc.txt',(err,fd)=>{
  if(err){
    console.log(err);
  }else{
    console.log(fd);
    // 通过文件描述符去操作文件
    fs.fstat(fd,(err,info)=>{
      console.log(info);
    })
  }
})
文件的读写

flag选项

  • w 打开文件写入,默认值
  • w+打开文件进行读写,如果不存在则创建文件;
  • r+ 打开文件进行读写,如果不存在那么抛出异常
  • r打开文件读取,读取时的默认值
  • a打开要写入的文件,将流放在文件末尾。如果不存在则创建文件
  • a+打开文件以进行读写,将流放在文件末尾。如果不存在则创建文件
const fs = require('fs');

// 1.文件写入
const content = "hello node";

fs.writeFile('./abc.txt', content, {flag: "a"}, err => {
  console.log(err);
});

// 2.文件读取
fs.readFile("./abc.txt", {encoding: 'utf-8'}, (err, data) => {
  console.log(data);
});

encoding选项:https://www.jianshu.com/p/899e749be47c

文件夹操作
const fs = require('fs')
const path = require('path')

// 1.创建文件夹
const dirname = './yihua'
// if (!fs.existsSync(dirname)) {
//   fs.mkdir(dirname, err => {
//     console.log(err)
//   })
// }

// 2.读取文件夹中的所有文件
fs.readdir(dirname, (err, files) => {
  console.log(files)
})

function getFiles (dirname) {
  fs.readdir(dirname, { withFileTypes: true }, (err, files) => {
    for (let file of files) {
      // fs.stat(file) 可以, 但是有点麻烦
      if (file.isDirectory()) {
        const filepath = path.resolve(dirname, file.name)
        getFiles(filepath)
      } else {
        console.log(file.name)
      }
    }
  })
}

getFiles(dirname)

// 3.重命名
fs.rename('./yihua', './test', err => {
  console.log(err)
})
文件夹的复制
const fs = require('fs')
const path = require('path')

const sourceDir = 'source'
const targetDir = './target'

const walkSync = (curDirPath, cb) => {
  fs.readdirSync(curDirPath, {withFileTypes: true}).forEach(dir => {
    const filePath = path.join(curDirPath, dir.name)
    if (dir.isFile()) {
      cb(filePath)
    }else if (dir.isDirectory()) {
      const dirname = path.join(curDirPath.replace(sourceDir, targetDir),dir.name)
      // 创建文件夹
      if (!fs.existsSync(dirname)) {
        fs.mkdir(dirname,err=>{
          console.log(err);
        })
      }
      walkSync(filePath, cb)
    }
  })
}

const copyFile = filePath => {
  console.log(filePath, filePath.replace(sourceDir, targetDir))
  fs.copyFile(filePath, filePath.replace(sourceDir, targetDir), (err) => {
    console.log(err)
  })
}

walkSync(sourceDir, copyFile)

events模块

发出事件和监听事件都是通过EventEmitter类来完成的,它们都属于events对象。

  • emitter.on(eventName, listener):监听事件,也可以使用addListener;
  • emitter.off(eventName, listener):移除事件监听,也可以使用removeListener;
  • emitter.emit(eventName[, …args]):发出事件,可以携带一些参数;
const EventEmitter = require('events')

// 1.创建发射器
const emitter = new EventEmitter()

// 2.监听事件
emitter.on('click', (...args) => {
  console.log('监听1', args)
})

const listener2 = (...args) => {
  console.log('监听2到click事件', args)
}
emitter.on('click', listener2)

// 3.触发事件
setTimeout(() => {
  emitter.emit('click', 'yihua', 18, '男')
  emitter.off('click', listener2)
  emitter.emit('click', 'yihua', 18, '男')
}, 2000)
常见的属性
  • emitter.eventNames():返回当前 EventEmitter对象注册的事件字符串数组;
  • emitter.getMaxListeners():返回当前 EventEmitter对象的最大监听器数量,可以通过setMaxListeners()来修改,默认是10;
  • emitter.listenerCount(事件名称):返回当前 EventEmitter对象某一个事件名称,监听器的个数
  • emitter.listeners(事件名称):返回当前 EventEmitter对象某个事件监听器上所有的监听器数组;
console.log(emitter.eventNames())
console.log(emitter.getMaxListeners())
console.log(emitter.listenerCount('click'))
console.log(emitter.listeners('click'))
方法的补充
  • emitter.once(eventName, listener):事件监听一次
  • emitter.prependListener():将监听事件添加到最前面
  • emitter.prependOnceListener():将监听事件添加到最前面,但是只监听一次
  • emitter.removeAllListeners([eventName]):移除所有的监听器
// 只执行一次
emitter.once('click', (...args) => {
  console.log('监听1到click事件', args)
})

// 将本次监听放到最前面
emitter.prependListener('click', (...args) => {
  console.log('监听2到click事件', args)
})

emitter.prependOnceListener('click', (...args) => {
  console.log('监听2到click事件', args)
})

emitter.removeAllListeners('click')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值