学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes
觉得有帮助的同学,可以点心心支持一下哈
一、Buffer
1.概念
Buffer中文译为【缓冲区】,是一个类似于Array的对象,用来表示固定长度的字节序列
简单理解:Buffer就是一段固定长度的内存空间,用于处理二进制数据
2.特点
①Buffer大小固定且无法调整
②Buffer性能较好,可以直接对计算机内存进行操作
③每个元素的大小为1字节(byte)
3.Buffer的创建
3.1alloc
// 1.alloc(分配)
let buf = Buffer.alloc(10)
// console.log(buf) //<Buffer 00 00 00 00 00 00 00 00 00 00>
3.2allocUnsafe
// 2.allocUnsafe(不安全的,可能会包含旧的内存数据,优点比alloc快)
let buf_2 = Buffer.allocUnsafe(10000)
// console.log(buf_2)
3.3from
// 3.from(将一个字符串或者数组转为Buffer)
let buf_3 = Buffer.from('hello')
let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117])
// console.log(buf_3) //<Buffer 68 65 6c 6c 6f>
console.log(buf_4) //<Buffer 69 6c 6f 76 65 79 6f 75>
4.Buffer与字符串的转化(toString)
toString默认是按照utf-8编码方式进行转换的
// buffer与字符串的转换
let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117])
console.log(buf_4.toString()) //iloveyou utf-8
5.Buffer的读写[ ]
Buffer可以直接通过[ ]的方式对数据进行处理
let buf = Buffer.from('hello')
console.log(buf[0].toString(2)) //01101000 toString是进制转换
console.log(buf) //<Buffer 68 65 6c 6c 6f>
buf[0] = 95
console.log(buf) //<Buffer 5f 65 6c 6c 6f>
console.log(buf.toString()) //_ello
注意:
①如果修改的数值超过255,则超过8位数据会被舍弃
②一个utf-8的字符一般占3个字节
// 溢出
let buf_1 = Buffer.from('hello')
buf_1[0] = 361 //超过了255,舍弃高位的数字 0001 0110 1001 =>0110 1001
console.log(buf_1) //<Buffer 69 65 6c 6c 6f>
// 中文
let buf_2 = Buffer.from('你好')
console.log(buf_2) //<Buffer e4 bd a0 e5 a5 bd> 一个utf-8占三个字节
二、计算机基础
计算机的基本组成
cpu、内存、硬盘
内存:读写速度较快,断电丢失数据
硬盘:读写速度较慢,断电不丢失数据
程序运行的基本流程
操作系统
操作系统也是一种应用程序,用来管理和调度硬件资源
计算机启动的基本过程
程序运行的基本过程
小结
程序一般保存在硬盘,软件安装的过程就是将程序写入硬盘的过程
程序在运行时会加载进入内存,然后由CPU读取并执行程序
进程与线程
进程
进行中的程序
进程是程序的一次执行过程
线程
线程是一个进程中执行的一个执行流,一个线程是属于某个进程的
线程和进程的关系
查看进程的线程(了解)
pslist -dmx 进程id
三、fs模块(file system 文件系统)
fs模块可以实现与硬盘的交互
例如文件的创建、删除、重命名、移动
1.fs写入文件
fs.writeFile 四个参数 (file,data[,options],callback)
file 文件名
data 代写入的数据
options 选项设置(可选)
callback 写入回调
返回值:undefined
/***需求:* 新建一个文件,座右铭.txt,写入内容,三人行,则必有我师焉*/// 1.导入fs模块
const fs = require('fs')
// 2.写入文件 四个参数 (file,data[,options],callback)
// file 文件名
// data 代写入的数据
// options 选项设置(可选)
// callback 写入回调
// 返回值:undefined
fs.writeFile('./座右铭.txt', '三人行,则必有我师焉', err => {// 如果写入失败,值为错误对象 写入成功:nullif (err) {console.log('写入失败')return}console.log('写入成功')
})
2.fs异步和同步
// 异步写入
fs.writeFile('./座右铭.txt', '三人行,则必有我师焉', err => {// 如果写入失败,值为错误对象 写入成功:nullif (err) {console.log('写入失败')return}console.log('写入成功')
})
// 同步写入
fs.writeFileSync('./test.txt', 'test')
3.文件追加写入
appendFile作用是在文件尾部追加内容,和writeFile语法完全相同
fs.appendFile (file,data[,options],callback)
fs.appendFileSync (file,data[,options])
返回值:二者都为undefined
①异步追加 fs.appendFile
②同步追加 fs.appendFileSync
③writeFile 实现追加写入(使用配置项)
// 1.引入fs模块
const fs = require('fs')
// 异步追加
// fs.appendFile('./座右铭.txt', ',择其善者而从之,择其不善者而改之', err => {
// if (err) {
// console.log('写入失败')
// return
// }
// console.log('追加写入成功')
// })// 同步追加
// fs.appendFileSync('./座右铭.txt', '\r\n温故而知新,可以为师矣')// writeFile 实现追加写入(使用配置项)
fs.writeFile('./座右铭.txt', 'love love love', { flag: 'a' }, err => {// 如果写入失败,值为错误对象 写入成功:nullif (err) {console.log('写入失败')return}console.log('写入成功')
})
4.createWriteStream流式写入
fs.createWriteStream 两个参数 (path[,options])
path 文件路径
options 选项配置(可选)
返回值:Object
程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数
流式写入方式适用于大文件写入或者频繁写入的场景,writeFile适合于写入频率较低的场景
/*** 观书有感.txt*/
// 1.导入fs模块
const fs = require('fs')// 2.创建写入流对象
const ws = fs.createWriteStream('./观书有感.txt')// 3.write
ws.write('1\r\n')
ws.write('2\r\n')
ws.write('3\r\n')// 4.关闭通道
ws.close()
5.文件写入应用场景
当需要持久化保存数据的时候,应该想到文件写入
①下载文件
②安装软件
③保存程序日志,如Git
④编辑器保存文件
⑤视频录制
6.文件读取
通过程序从文件中取出其中的数据
①readFile 异步读取
②readFileSync 同步读取
③createReadStream 流式读取
// 1.引入fs模块
const fs = require('fs')// 2.异步读取
fs.readFile('./观书有感.txt', (err, data) => {if (err) {console.log('读取失败~~')return}console.log(data.toString())
})// 2.同步读取
let str = fs.readFileSync('./观书有感.txt')
console.log(str.toString())// 3.创建读取流对象
const rs = fs.createReadStream('./素材/慢热的气球 - 在你的身边 (慢放版).ogg')
// 3.1绑定data事件 chunk块儿 大块儿
rs.on('data', chunk => {console.log(chunk.length) //65536字节=> 64kB
})
// 3.2end 可选事件
rs.on('end', () => {console.log('读取完成')
})
7.文件读取应用场景
①电脑开机
②程序运行
③编辑器打开文件
④查看图片
⑤播放视频
⑥播放音乐
⑦Git查看日志
⑧上传文件
⑨查看聊天记录
案例(复制文件)
流式操作内存使用更少,效率更高
/*** 需求:* 复制【素材】文件夹下的慢热的气球 - 在你的身边 (慢放版).ogg*/
const fs = require('fs')
// 方式一 readFile
let data = fs.readFileSync('./素材/慢热的气球 - 在你的身边 (慢放版).ogg')
fs.writeFileSync('./素材/慢热的气球 - 在你的身边 (慢放版)_复制版.ogg', data)
// 方式二 流式操作
// 创建读取流对象
const rs = fs.createReadStream('./素材/慢热的气球 - 在你的身边 (慢放版).ogg')
// 创建写入流对象
const ws = fs.createWriteStream('./素材/慢热的气球 - 在你的身边 (慢放版)_复制版.ogg'
)
// 绑定data事件 chunk 大块 大块儿
rs.on('data', chunk => {// chunk每次读取的数据(64kb)ws.write(chunk)
})
rs.on('end', () => {console.log('读取复制完成')
})
8.文件重命名与移动
使用rename或renameSync来移动或重命名文件或文件夹
语法:
fs.rename(oldPath,newPath,callback)
fs.renameSync (oldPath,newPath)
参数说明:
oldPath 文件当前的路径
newPath 文件新的路径
callback 操作后的回调
const fs = require('fs')
// 文件的重命名
fs.rename('./座右铭.txt', './右铭.txt', err => {if (err) {console.log('修改失败')return}console.log('修改成功')
})
// 文件的移动
fs.rename('./右铭.txt', './素材/右铭.txt', err => {if (err) {console.log('移动失败')return}console.log('移动成功')
})
9.文件删除
使用unlink或unlinkSync来删除文件
使用rm方法 node14.4支持 也有相应的同步删除rmSync
unlink 不能用于删除文件夹,rm 可以删除文件和文件夹
语法:
fs.unlink(path,callback)
fs.unlinkSync(path)
参数说明:
path 文件路径
callback 操作后的回调
const fs = require('fs')
// 使用unlink或unlinkSync来删除文件
fs.unlink('./test.txt', err => {if (err) {console.log('删除失败')return}console.log('删除成功')
})
// 使用rm方法 node14.4支持 也有相应的同步删除rmSync
fs.rm('./test.txt', err => {if (err) {console.log('删除失败')return}console.log('删除成功')
})
10.文件夹操作
1.创建文件夹
使用mkdir或mkdirSync来创建文件夹
语法:
fs.mkdir(path[,options],callback)
fs.mkdirSync(path[,options])
参数说明:
path 文件夹路径
options 选项设置(可选)
callback 操作后的回调
// 同步创建
fs.mkdirSync('./test')
// 同步创建——递归创建 recursive递归
fs.mkdirSync('./a/b/c', { recursive: true })
// 异步创建
fs.mkdir('./test', err => {if (err) {console.log('创建失败')return}console.log('创建成功')
})
// 同步创建——递归创建 recursive递归
fs.mkdir('./a/b/c', { recursive: true }, err => {if (err) {console.log('创建失败')return}console.log('创建成功')
})
2.读取文件夹
使用readdir或readdirSync来读取文件夹
语法:
fs.readdir(path[,options],callback)
fs.readdirSync(path[,options])
参数说明:
path 文件夹路径
options 选项设置(可选)
callback 操作后的回调
// 获取文件夹(同步)
console.log(fs.readdirSync('./'))
// 获取文件夹(异步)
fs.readdir('./', (err, data) => {if (err) {console.log('获取文件夹失败')return}console.log(data)
})
3.删除文件夹
使用rmdir(不推荐使用,后面会舍弃)
使用rm(推荐使用)
目录里面还有内容需要用到配置项recursive
语法:
fs.rm(path[,options],callback)
fs.rmSync(path[,options])
参数说明:
path 文件夹路径
options 选项设置(可选)
callback 操作后的回调
// //递归删除文件夹(同步),目录里面还有内容需要用到配置项recursive
fs.rmSync('./a', { recursive: true })
//递归删除文件夹(异步)
fs.rm('./a', { recursive: true }, err => {if (err) {console.log(err)return}console.log('删除成功')
})
11.查看资源状态
使用stat或statSync来查看资源的详细信息
语法:
fs.stat(path[,options],callback)
fs.statSync(path[,options])
参数说明:
path 文件夹路径
options 选项设置(可选)
callback 操作后的回调
结果值对象结构:
- size 文件体积
- birthtime 创建时间
- mtime 最后修改时间
- isFile 检测是否为文件
- isDirectory 检测是否为文件夹
const fs = require('fs')
// 使用stat来查看资源的详细信息
fs.stat('./素材/慢热的气球 - 在你的身边 (慢放版).ogg', (err, data) => {if (err) {console.log('查看失败')return}console.log(data)
})
12.路径补充说明(相对路径的Bug与解决)
fs模块对资源进行操作时,路劲的写法有两种:
相对路径:
- ./座右铭.txt 当前目录下的座右铭.txt
- 座右铭.txt 等效于上面的写法
- ../座右铭.txt 当前目录的上一级目录中的座右铭.txt
绝对路径:
D:/software windows系统下的绝对路径
/software linux系统下的绝对路径
相对路径中所谓的当前目录,指的是命令行的工作目录,而并非时文件的所在目录·
__dirname
__dirname与require类似,都是Node.js环境中的全局变量
__dirname保存着当前文件所在目录的绝对路径,可以使用__dirname与文件名拼接成绝对路径
使用fs模块的时候,尽量使用__dirname将路径转化为绝对路径,这样可以避免相对路径产生的Bug
const fs = require('fs')
// __dirname保存着当前文件所在目录的绝对路径,可以使用__dirname与文件名拼接成绝对路径
console.log(__dirname)
fs.writeFileSync(__dirname + '/test.html', 'love')
案例(批量重命名)
// 1.导入fs模块
const fs = require('fs')
// 2.读取文件夹
const fsDir = fs.readdirSync('./')
fsDir.forEach(item => {// 根据-把字符串转为数组let data = item.split('-')// 数组结构let [num, name] = data// 判断是否>10,进行字符串拼接if (Number(num) < 10) {num = '0' + num}// 创建新的文件名let newFileName = num + name// 重命名fs.renameSync(`./${item}`, `./${newFileName}`)
})
四、path模块
path模块提供一些操作路径的功能
path.reslove 拼接规范的绝对路径
path.sep 获取操作系统的路径分隔符
path.basename 获取路径的基础名称
path.dirname 获取路径的目录名
path.extname 获取路径的扩展名
// 引入相应模块
const fs = require('fs')
const path = require('path')
// __dirname保存着当前文件所在目录的绝对路径,可以使用__dirname与文件名拼接成绝对路径,不规范
console.log(__dirname + '/test.html') //E:\code\WebCode\vue\node_basic/test.html 不规范
// 拼接规范的绝对路径 (第一个参数绝对路径,后面的参数都为相对路径)
console.log(path.resolve(__dirname, './test.html')) //E:\code\WebCode\vue\node_basic\test.html
console.log(path.resolve(__dirname, 'test.html')) //E:\code\WebCode\vue\node_basic\test.html
console.log(path.resolve(__dirname, '/test.html')) //E:\test.html
let str = 'E:\\code\\WebCode\\vue\\node_basic\\test.html'
// 获取操作系统的路径分隔符
console.log(path.sep) //windows: \ linux: /
// 获取文件的绝对路径
console.log(__filename) //E:\code\WebCode\vue\node_basic\14-path模块.js
// 获取文件目录的绝对路径
console.log(__dirname) //E:\code\WebCode\vue\node_basic
// 获取路径的基础名称
console.log(path.basename(str)) //test.html
// 获取路径的目录名
console.log(path.dirname(str)) //E:\code\WebCode\vue\node_basic
// 获取路径的扩展名
console.log(path.extname(str)) //.html