NodeJs全局变量、Path模块、Fs模块

一、NodeJs全局对象global

全局对象是JS中的特殊对象,它与浏览器平台的window不完全相同,Nodejs中全局对象是global.它的根本作用就是作为宿主,全局对象可以看做全局变量的宿主,Nodejs全局对象上挂载许多属性.

NodeJs常见全局变量

  • __filename: 返回正在执行脚本文件的绝对路径
  • __dirname: 返回正在执行脚本所在目录
  • timer类函数: 执行顺序事件循环间的关系
  • require: 实现模块的加载
  • module、exports: 处理模块的导出
  • process: 提供与当前进程互动的接口
    • 内存情况: process.memoryUsage()
    • CPU情况: process.cpuUsage()
    • 运行目录: process.cwd()
    • node环境: process.version process.versions
    • cpu架构: process.arch
    • 用户环境: process.env.NODE_ENV process.env.PATH
    • 获取用户工作目录: process.env.USERPROFILE process.env.HOME(mac下)
    • 系统平台: process.platform
    • 启动参数: process.argv process.execArgv
    • pid: process.pid process.ppid
    • 运行时间: process.uptime()
    • 输入输出事件流:
      // 设置字符编码
      process.stdin.setEncoding('utf-8')
      // 设置一个是否可读的事件readable
      process.stdin.on('readable',()=>{
      	// 取出可读的东西
      	let chunk = process.stdin.read()
      	if(chunk !== null){
      		// 写出来
      		process.stdout.write('data'+ chunk)
      	}
      })
      

二、NodeJs核心模块

2.1 Path模块常用API

Path模块用于处理文件/目录的路径

  • basename() 获取路径中基础名称
// 01 返回的就是接收路径当中的最后一部分
console.log(path.basename(__filename)) // 01-path.js
// 02 第二个参数表示扩展名,如果说没有设置则返回完整的文件名称带后缀
console.log(path.basename(__filename, '.js')) // 01-path
// 03 第二个参数做为后缀时,如果没有在当前路径中被匹配到,那么就会忽略
console.log(path.basename(__filename, '.css')) //01-path.js
// 04 处理目录路径的时候如果说,结尾处有路径分割符,则也会被忽略掉
console.log(path.basename('/a/b/c')) // c
console.log(path.basename('/a/b/c/')) // c
  • dirname() 获取路径目录名 (路径)
// 返回路径中最后一个部分的上一层目录所在路径
console.log(path.dirname(__filename)) // /Users/.../02Path
console.log(path.dirname('/a/b/c')) // /a/b
console.log(path.dirname('/a/b/c/')) // /a/b
  • extname() 获取路径中扩展名称
// 返回路径中最后一个部分的上一层目录所在路径
console.log(path.extname(__filename)) // .js
console.log(path.extname('/a/b')) // 
// 如果 path 路径当中存在多个点,它匹配的是最后一个点,到结尾的内容
console.log(path.extname('/a/b/index.html.js.css')) // .css
// 如果 path 路径当中存在多个点,它匹配的是最后一个点,到结尾的内容
console.log(path.extname('/a/b/index.html.js.'))  // .
  • isAbsolute() 判断获取路径是否为绝对路径
console.log(path.isAbsolute("foo")); //  false
console.log(path.isAbsolute("/foo")); //  true
console.log(path.isAbsolute("///foo")); //  true
console.log(path.isAbsolute("")); //  false
console.log(path.isAbsolute(".")); //  false
console.log(path.isAbsolute("../bar")); //  false
  • join() 拼接多个路径片段
console.log(path.join('a/b', 'c', 'index.html')) // a/b/c/index.html
console.log(path.join('/a/b', 'c', 'index.html')) // /a/b/c/index.html
console.log(path.join('/a/b', 'c', '../', 'index.html')) // /a/b/index.html
console.log(path.join('/a/b', 'c', './', 'index.html')) // /a/b/c/index.html
console.log(path.join('/a/b', 'c', '', 'index.html')) // /a/b/c/index.html
console.log(path.join('')) // .
  • resolve() 返回绝对路径
console.log(path.resolve()) // /Users/***/path
console.log(path.resolve('/a', '/')) // /
console.log(path.resolve('/a', '/b')) // /b
console.log(path.resolve('/a', '../b')) // /b
console.log(path.resolve('a', 'b')) // /Users/***/a/b
console.log(path.resolve('index.html')) // /Users/***/path/index.html
  • pasre() 解析路径
// { root: '/', dir: '/a/b/c', base: 'index.html', ext: 'html', name: 'index' }
console.log(path.parse('/a/b/c/index.html')) 
// { root: '/', dir: '/a/b', base: 'c', ext: '', name: 'c' }
console.log(path.parse('/a/b/c/'))
// { root: '', dir: './a/b', base: 'c', ext: '', name: 'c' }
console.log(path.parse('./a/b/c/'))
  • format() 序列化路径
const obj = path.parse('./a/b/c/')
console.log(path.format(obj)) // ./a/b/c
  • normalize() 规范化路径
console.log(path.normalize('')) // .
console.log(path.normalize('a/b/c/d')) // a/b/c/d
console.log(path.normalize('a///b/c../d')) // a/b/c../d
console.log(path.normalize('a//\\/b/c\\/d')) // a/\/b/c\/d
console.log(path.normalize('a//\b/c\\/d')) // a/c\/d

2.2 全局变量之Buffer

Nodejs平台js可以实现IO,IO行为操作其实就是操作二进制数据,而buffer让js可以操作二进制.Buffer是Nodejs的内置类是一片内存空间,目的是为了方便让cpu进行存取操作的时候可以有一个中间的存储区域
buffer是什么?在哪?做什么?

Buffer总结
  • 无需require的一个全局变量
  • 实现Nodejs平台下的二进制数据操作
  • 不占据V8堆内存大小的内存空间
  • 内存的使用由Node来控制,由V8的GC回收
  • 一般配合Stream流使用,充当数据缓冲区
    请添加图片描述
创建Buffer
  • alloc 创建制定字节大小的buffer
// Buffer是一种内存空间的数据类型, 创建10个字节的buffer
const b1 = Buffer.alloc(10)
  • allocUnsafe 创建制定大小的buffer(不安全)
// 在内存中只要有空闲的空间(没有被垃圾回收的空间)就会拿过来使用,用的比较少
const b2 = Buffer.allocUnsafe(10)
console.log(b1)// <Buffer 00 00 00 00 00 00 00 00 00 00>
console.log(b2)// <Buffer 08 00 00 00 01 00 00 00 00 00>
  • from 接收数据,创建buffer
// 接收数据创建buffer 返回对应字符的16进制编码
const b3 = Buffer.from('中')
console.log(b3) // <Buffer e4 b8 ad>

const b4 = Buffer.from([0xe4, 0xb8, 0xad])
console.log(b4); // <Buffer e4 b8 ad>
console.log(b4.toString()); // 中

// 接收一个buffer生产的是一个新的buffer,内存空间是独立的
const b5= Buffer.alloc(3)
const b6 = Buffer.from(b5)
console.log(b5) // <Buffer 00 00 00>
console.log(b6) // <Buffer 00 00 00>
b5[0] = 1 // 修改
console.log(b5) // <Buffer 01 00 00>
console.log(b6) // <Buffer 00 00 00>
Buffer实例方法
let buf = Buffer.alloc(6);
  • fill : 使用数据填充buffer
buf.fill(123,1)
buf.fill(123)
console.log(buf) // <Buffer 7b 7b 7b 7b 7b 7b>
console.log(buf.toString()) // {{{{{{
  • write : 向buffer中写入数据
// 第二个参数是写入的位置 第三个参数是写入的长度
buf.write('123', 1, 4)
console.log(buf) // <Buffer 00 31 32 33 00 00>
console.log(buf.toString()) // 123
  • toString : 从buffer中提取数据
buf = Buffer.from('韬光养晦')
console.log(buf) // <Buffer e9 9f ac e5 85 89 e5 85 bb e6 99 a6>
console.log(buf.toString('utf-8', 6, 12)) // 养晦
  • slice : 截取buffer
buf = Buffer.from("韬光养晦");
console.log(buf); // <Buffer e9 9f ac e5 85 89 e5 85 bb e6 99 a6>
let b1 = buf.slice(-3);
console.log(b1); // <Buffer e6 99 a6>
console.log(b1.toString()); // 晦
  • indexOf : 在buffer中查找数据
// indexOf 查找是否存在并返回下标
buf = Buffer.from('爱前端')
console.log(buf) // <Buffer e7 88 b1 e5 89 8d e7 ab af>
console.log(buf.indexOf('前')) // 3
  • copy : 拷贝buffer中的数据
let b1 = Buffer.alloc(12)
let b2 = Buffer.from('学习')
// 将b2拷贝给b1 b1是容器 第一个3表示放置在b1的第三个位置 后面的3和6表示拷贝b2的第三个到第6个字节
b2.copy(b1,3,3,6)
console.log(b1.toString()) // 习
console.log(b2.toString()) // 学习

// 将b2拷贝给b1 第一个3表示放置在b1的第三个位置
b2.copy(b1,3)
console.log(b1.toString()) // 学
console.log(b2.toString()) // 学习

// 将b2拷贝给b1 第一个3表示放置在b1的第三个位置 第二个3表示拷贝b2的第三个到最后一个
b2.copy(b1,3,3)
console.log(b1.toString()) // 习
console.log(b2.toString()) // 学习

// 将b2全部拷贝给b1 从b1的开始位存起
b2.copy(b1)
console.log(b1.toString()) // 学习
console.log(b2.toString()) // 学习
Buffer静态方法
  • concat : 将多个buffer拼接成一个新的buffer
let b1 = Buffer.from('拉勾')
let b2 = Buffer.from('教育')
let b = Buffer.concat([b1, b2])
console.log(b) // <Buffer e6 8b 89 e5 8b be e6 95 99 e8 82 b2>
console.log(b.toString()) // 拉勾教育
// 取前几位
let b2 = Buffer.concat([b1, b2],9)
console.log(b.toString()) // 拉勾教
  • isBuffer : 判断当前数据是否为buffer
// isBuffer
let b1 = '123'
console.log(Buffer.isBuffer(b1)) // false
自定义Buffer之split
ArrayBuffer.prototype.split = function (sep) {
  let len = Buffer.from(sep).length
  let ret = []
  let start = 0
  let offset = 0

  while( offset = this.indexOf(sep, start) !== -1) {
    ret.push(this.slice(start, offset))
    start = offset + len
  }
  ret.push(this.slice(start)) 
  return ret
}

let buf = 'zce吃馒头,吃面条,我吃所有吃'
let bufArr = buf.split('吃')
console.log(bufArr)

2.3 FS模块

FS是内置的核心模块,提供文件系统操作的API,在使用的过程中buffer(缓冲区)steram(数据流)是绕不开的. fs分为基本操作类常用api部分 请添加图片描述

先说一说文件
  • 权限位
    • 用户对于文件所具备的操作权限.分别是R(读权限,对应八进制是4)、W(写权限,对应八进制是2)、S(执行权限,对应八进制是1) ,不具备操作权限是0. 操作系统将用户又分为3类,当前所有者(自己)、文件所属组(家人)、其他用户(其他人)请添加图片描述
  • flag标识符
    • r: 表示可读
      • r+: 不清空,直接写.写在前
    • w: 表示可写
      • w+: 清空再写
    • s: 表示同步操作
    • +: 表示执行相反操作
    • x: 表示排他的操作方式
    • a: 表示追加操作
  • 文件描述符
    • 操作系统中文件描述符一般从3开始,0(标准输入)、1(标准输出)、2 (标准错误)已经被占用了.
    • 在后期执行fs.open打开某一个文件的时候会得到一个fd, fd就是从3开始的.
    • 而fd就是操作系统分配给被打开文件的描述符
文件操作API
  • readFile: 从指定文件中读取数据
    • 如果路径不存在会报错
// 在node中遵循错误优先
fs.readFile(path.resolve("data.txt"), "utf-8", (err, data) => {
  console.log(err);
  if (!null) {
    console.log(data);
  }
});
  • writeFile: 向指定文件中写入数据
    • 如果路径不存在就会去创建文件
fs.writeFile('data.txt', '123', {
  mode: 438,// 操作权限:在windows八进制中对应0o666,对应的十进制是438,也就是可读可写不可执行
  flag: 'w+',// w+: 写入方式,清空再写入  r+:不清空,在第一个位置写入
  encoding: 'utf-8'// 字符编码
}, (err) => {
  if (!err) {
    fs.readFile('data.txt', 'utf-8', (err, data) => {
      console.log(data)
    })
  }
})
  • appendFile: 追加的方式向文件中写入数据
fs.appendFile('data.txt', 'hello node.js',{},  (err) => {
  console.log('写入成功')
})
  • copyFile: 将某个文件中的数据拷贝到另一文件
fs.copyFile('data.txt', 'test.txt', () => {
  console.log('拷贝成功')
})
  • watchFile: 对指定文件进行监控
fs.watchFile("data.txt", { interval: 20 }, (curr, prev) => {
  // interval: 每20s监控一下,文件是否发生变化.发生变化了执行回调函数
  // mtime: 修改时间
  // curr: 修改之后的信息 prev:修改之前的信息
  if (curr.mtime !== prev.mtime) {
    console.log("文件被修改了");
    fs.unwatchFile("data.txt");
  }
});
文件操作实现md转html
const fs = require('fs')
const path = require('path')
const { marked } = require('marked'); // npm init npm i marked
const browserSync = require('browser-sync') // npm i browser-sync

/**
 * 01 读取 md 和 css 内容
 * 02 将上述读取出来的内容替换占位符,生成一个最终需要展的 Html 字符串 
 * 03 将上述的 Html 字符写入到指定的 Html 文件中
 * 04 监听 md 文档内容的变经,然后更新 html 内容 
 * 05 使用 browser-sync 来实时显示 Html 内容
 */

let mdPath = path.join(__dirname, 'index.md')
console.log(mdPath);
let cssPath = path.resolve('github.css')
let htmlPath = mdPath.replace(path.extname(mdPath), '.html')
const read = () => {
  fs.readFile(mdPath, 'utf-8', (err, data) => {
    // 将 md--》html
    let htmlStr = marked(data)
    console.log(htmlStr);
    fs.readFile(cssPath, 'utf-8', (err, data) => {
      let retHtml = temp.replace('{{content}}', htmlStr).replace('{{style}}', data)
      // 将上述的内容写入到指定的 html 文件中,用于在浏览器里进行展示
      fs.writeFile(htmlPath, retHtml, (err) => {
        console.log('html 生成成功了')
      })
    })
  })
}

fs.watchFile(mdPath, (curr, prev) => {
  if (curr.mtime !== prev.mtime) {
    read()
  }
})

read()

browserSync.init({
  browser: '',
  server: __dirname,
  watch: true,
  index: path.basename(htmlPath)
})

const temp = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .markdown-body {
                box-sizing: border-box;
                min-width: 200px;
                max-width: 1000px;
                margin: 0 auto;
                padding: 45px;
            }
            @media (max-width: 750px) {
                .markdown-body {
                    padding: 15px;
                }
            }
            {{style}}
        </style>
    </head>
    <body>
        <div class="markdown-body">
            {{content}}
        </div>
    </body>
    </html>
文件打开与关闭

fs.open打开某一个文件的时候会得到一个fd, fd就是从3开始的.
而fd就是操作系统分配给被打开文件的描述符

const fs = require('fs')
const path = require('path')

// open 
fs.open(path.resolve('data.txt'), 'r', (err, fd) => {
  console.log(fd)
})

// close
fs.open('data.txt', 'r', (err, fd) => {
  console.log(fd)
  fs.close(fd, err => {
    console.log('关闭成功')
  })
})
大文件读写操作

请添加图片描述

const fs = require('fs')

// read : 所谓的读操作就是将数据从磁盘文件中写入到 buffer 中
let buf = Buffer.alloc(10)

/**
 * fd 定位当前被打开的文件 
 * buf 用于表示当前缓冲区
 * offset 表示当前从 buf 的哪个位置开始执行写入
 * length 表示当前次写入的长度
 * position 表示当前从文件的哪个位置开始读取
 */
fs.open('data.txt', 'r', (err, rfd) => {
  console.log(rfd)
  fs.read(rfd, buf, 1, 4, 3, (err, readBytes, data) => {
    console.log(readBytes)
    console.log(data)
    console.log(data.toString())
  })
})

// write 将缓冲区里的内容写入到磁盘文件中
buf = Buffer.from('1234567890·')
fs.open('b.txt', 'w', (err, wfd) => {
  fs.write(wfd, buf, 2, 4, 0, (err, written, buffer) => {
    console.log(written, '----')
    fs.close(wfd)
  })
})
文件拷贝自定义实现
const fs = require('fs')

/**
 * 01 打开 a 文件,利用 read 将数据保存到 buffer 暂存起来
 * 02 打开 b 文件,利用 write 将 buffer 中数据写入到 b 文件中
 */
let buf = Buffer.alloc(10)

// 01 打开指定的文件
// fs.open('a.txt', 'r', (err, rfd) => {
//   // 03 打开 b 文件,用于执行数据写入操作
//   fs.open('b.txt', 'w', (err, wfd) => {
//     // 02 从打开的文件中读取数据
//     fs.read(rfd, buf, 0, 10, 0, (err, readBytes) => {
//       // 04 将 buffer 中的数据写入到 b.txt 当中
//       fs.write(wfd, buf, 0, 10, 0, (err, written) => {
//         console.log('写入成功')
//       })
//     })
//   })
// })

// 02 数据的完全拷贝
// fs.open('a.txt', 'r', (err, rfd) => {
//   fs.open('b.txt', 'a+', (err, wfd) => {
//     fs.read(rfd, buf, 0, 10, 0, (err, readBytes) => {
//       fs.write(wfd, buf, 0, 10, 0, (err, written) => {
//         fs.read(rfd, buf, 0, 5, 10, (err, readBytes) => {
//           fs.write(wfd, buf, 0, 5, 10, (err, written) => {
//             console.log('写入成功')
//           })
//         })
//       })
//     })
//   })
// })

const BUFFER_SIZE = buf.length
let readOffset = 0

fs.open('a.txt', 'r', (err, rfd) => {
  fs.open('b.txt', 'w', (err, wfd) => {
    function next () {
      fs.read(rfd, buf, 0, BUFFER_SIZE, readOffset, (err, readBytes) => {
        console.log(readBytes);
        if (!readBytes) {
          // 如果条件成立,说明内容已经读取完毕
          fs.close(rfd, ()=> {})
          fs.close(wfd, ()=> {})
          console.log('拷贝完成')
          return
        }
        readOffset += readBytes
        fs.write(wfd, buf, 0, readBytes, (err, written) => {
          next()
        })
      })
    }
    next()
  })
})
FS之目录操作API
  • access: 判断文件或者目录是否具有操作权限,或者判断当前文件是否存在
fs.access('a.txt', (err) => {
  if (err) {
    console.log(err)
  } else {
    console.log('有操作权限')
  }
})
  • stat: 获取目录及文件信息
fs.stat('a.txt', (err, statObj) => {
  console.log(statObj)
  console.log(statObj.size)
  console.log(statObj.isFile())
  console.log(statObj.isDirectory())
})

  • mkdir: 创建目录
fs.mkdir('a/b/c', {recursive: true}, (err) => {
  if (!err) {
    console.log('创建成功')
  }else{
    console.log(err)
  }
})
  • rmdir: 删除目录
fs.rmdir('a/b', {recursive: true}, (err) => {
  if (!err) {
    console.log('删除成功')
  } else {
    console.log(err)
  }
})
  • readdir: 读取目录中的内容
fs.readdir('a/b/c', (err, files) => {
  console.log(files)
})
  • unlink: 删除指定文件
fs.unlink('a/b/c/index.html', (err) => {
  if (!err) {
    console.log('删除成功')
  }
})
创建目录之同步实现(mkdirSync)
const fs = require('fs')
const path = require('path')

/**
 * 01 将来调用时需要接收类似于 a/b/c ,这样的路径,它们之间是采用 / 去行连接
 * 02 利用 / 分割符将路径进行拆分,将每一项放入一个数组中进行管理  ['a', 'b', 'c']
 * 03 对上述的数组进行遍历,我们需要拿到每一项,然后与前一项进行拼接 /
 * 04 判断一个当前对拼接之后的路径是否具有可操作的权限,如果有则证明存在,否则的话就需要执行创建
 */

function makeDirSync(dirPath) {
  console.log(dirPath);
  let items = dirPath.split(path.sep)
  console.log(items);
  for (let i = 1; i <= items.length; i++) {
    let dir = items.slice(0, i).join(path.sep)
    try {
      fs.accessSync(dir)
    } catch (err) {
      fs.mkdirSync(dir)
    }
  }
}
const str  =  path.join(__dirname, 'a\\b\\c')
console.log(str);
makeDirSync(str)
创建目录之异步实现(mkdir)
const fs = require('fs')
const path = require('path')
const {promisify} = require('util')

// function mkDir (dirPath, cb) {
//   let parts = dirPath.split('/')
//   let index = 1

//   function next () {
//     if (index > parts.length) return cb && cb()

//     let current = parts.slice(0, index++).join('/')

//     fs.access(current, (err) => {
//       if (err) {
//         fs.mkdir(current, next)
//       }else{
//         next()
//       }
//     })
//   }
//   next()
// }

// mkDir('a/b/c/d', () => {
//   console.log('创建成功')
// })


// 将 access 与 mkdir 处理成 async... 风格
const access = promisify(fs.access)
const mkdir = promisify(fs.mkdir)

async function myMkdir (dirPath, cb) {
  let parts = dirPath.split('/')
  for(let index = 1; index <= parts.length; index++) {
    let current = parts.slice(0, index).join('/')
    try {
      await access(current)
    } catch (err) {
      await mkdir(current)
    }
  }
  cb && cb()
}

myMkdir('a/b/c/e', () => {
  console.log('创建成功')
})
递归删除或文件
const { dir } = require('console')
const fs = require('fs')
const path = require('path')
function myRmdir(dirPath, cb) {
  // 判断当前 dirPath 的类型
  fs.stat(dirPath, (err, statObj) => {
    console.log(dirPath);
    if (!err) {
      if (statObj.isDirectory()) {
        fs.rmdir(dirPath,cb)
      } else {
        // 文件---> 直接删除
        fs.unlink(dirPath, cb)
      }
    }

  })
}

myRmdir(path.join(__dirname, 'a/b/c/e/d/txt.txt'), (err) => {
  console.log('删除成功了')
})
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值