1.0 CMD常用命令
1.1 切换盘符
比如打开的c盘切换到d盘
d:
1.2 切换文件夹
// 先查看d盘的目录(文件夹)
dir
// dir /s 会输出所有子文件目录
// 切换到你想去的文件夹
cd node-progress
// 回到上一个目录
cd ..
2.0 初体验node
1.0 node 不能使用BOM和DOM的API,可以使用console和定时器API
2.0 node中的顶级对象是global,当然es2020增加了一个新的顶级对象globalThis,他们两个是相等的。
3.0 Buffer
3.1概念
Buffer:缓冲区,是一个类似于Array的对象,用于表示固定长度的字节序列,
换句话说,Buffer 就是一段固定长度的内存空间,用于处理二进制数据
3.1特点
1.0 大小固定不能调整
2.0 性能好,可以直接对计算机内存进行操作
3.0 每个元素的大小为1字节(byte)
扩展:什么是内存?
内存是计算机的重要部件,也称内存储器和主存储器,用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行,内存性能的强弱影响计算机整体发挥的水平。只要计算机开始运行,操作系统就会把需要运算的数据从内存调到CPU中进行运算,当运算完成,CPU将结果传送出来。
3.2使用
创建
// 1.0 alloc
let buf = Buffer.alloc(10)
console.log(buf)
// <Buffer 00 00 00 00 00 00 00 00 00 00>
// 2.0 allocUnsafe // 不安全的 大概率包含旧的内存数据
let buf1 = Buffer.allocUnsafe(10)
console.log(buf1)
// <Buffer 90 f5 74 f8 65 02 00 00 ff ff>
// 3.0 from
let buf2 = Buffer.from('hello')
// 创建一个包含 UTF-8 字节的buffer
console.log(buf2)
// <Buffer 68 65 6c 6c 6f>
// 也可以处理 数组
const buf4 = Buffer.from([1, 2, 3]);
console.log(buf4)
//<Buffer 01 02 03>
const buf6 = Buffer.from('tést', 'latin1');
console.log(buf6)
// <Buffer 74 e9 73 74>
操作buffer
// buffer 转为字符串
let buf_1 = Buffer.from([105,108,111,118,101])
console.log(buf_1.toString())
// ilove 默认采用uft-8的方式进行的转换当然也能 进行其它码的转换
buffer的读写
let buf = Buffer.from('hello')
// 查看第一个元素保存的数据 默认十进制
console.log(buf[0]) // 104
// 我要看看二进制的
console.log(buf[0].toString(2)) // 1101000
// 对元素进行修改
console.log(buf) // <Buffer 68 65 6c 6c 6f>
buf[0] = 99;
console.log(buf.toString()) // cello
// 中文 一个中文占3个字节
let buf1 = Buffer.from('你好')
console.log(buf1)
// <Buffer e4 bd a0 e5 a5 bd>
总结:
- Buffer 的结构与数组类似,操作方法也与数组类似
- 数组不能存储二进制文件,Buffer 是专门存储二进制数据的
- Buffer 存储的是二进制数据,显示时以 16 进制的形式显示
- Buffer 每一个元素范围是 00 ~ ff,即 0 ~ 255、00000000~11111111
- 每一个元素占用一个字节内存
- Buffer 是对底层内存的直接操作,因此大小一旦确定就不能修改
4.0 进程和线程
进程:进行中的程序
线程:是一个进程中执行的一个执行流,一个线程是属于某个进程的
5.0 fs模块
fs:file system 文件系统
fs模块可以实现与硬盘的交互
例如:文件的创建,删除,重命名,移动,
还有文件内容的写入,读取,
以及文件夹的相关操作。
5.1 文件的写入(writeFile)
// 1.0 导入模块
const fs = require('fs')
// 2.0 写入文件
// 如果没有这个文件会新建一个
fs.writeFile('./你好.txt','hello world!我是写入的内容',err=>{
// err 写入失败:返回错误对象 写入成功: 返回 null
if(err){
console.log('写入失败了')
return
}
console.log('我是回调函数')
})
注意: 该方法写入的内容是覆盖形式的,意思就是第一次写的内容是111,写一次还这样写入内容是222,则你好.txt里面的内容就是 222
5.2 fs的同步和异步
我们上面的writeFile就是异步任务。
接下来看看同步任务
// 1.0 导入模块
const fs = require('fs')
// 2.0 写入文件
// 如果没有这个文件会新建一个
fs.writeFile('./你好.txt','hello world!我是写入的内容',err=>{
// err 写入失败:返回错误对象 写入成功: 返回 null
if(err){
console.log('写入失败了')
return
}
console.log('我是回调函数1')
})
// 同步写入
fs.writeFileSync('./你好1.txt','11111')
console.log('结束')
// 运行这个文件 打印结果是
// 结束
// 我是回调函数1
// 证明异步任务是等主线程完成之后才,进入的主线程
5.3追加写入
// 1.0 引入模块
const fs = require('fs')
// 2.0 调用appendFile
fs.appendFile('./你好.txt',',我是追加的内容',err=>{
// 错误是个对象 成功是个null
if(err){
console.log('发生错误了')
return
}
console.log('追加成功')
})
// 2.2 同步追加写入
fs.appendFileSync('./你好.txt','\r\n我是同步追加')
// \r\n 是换行
// 2.3 writeFile 追加写入
fs.writeFile('./你好.txt','llllll',{flag:'a'},err=>{})
// 增加参数 {flag:'a'} 及表示追加写入
5.4文件流写入createWriteStream
// 1.0 导入
const fs = require('fs')
// 2.0 创建写入流对象
let ws = fs.createWriteStream('./天气.txt')
// 3.0 写入内容
ws.write('星期一 晴天\r\n');
ws.write('星期二 阴天\r\n');
ws.write('星期三 下雨\r\n');
// 4.0 关闭通道
ws.close()
程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数流式写入适合
大文件写入或者频繁写入的场景,writeFile 适用于写入频率低的场景
5.5写入文件的场景
当需要持久化保存数据的时候,应该想到文件写入
5.6文件读取
| 方法 | 说明 |
|---|---|
| readFile | 异步读取 |
| readFileSync | 同步读取 |
| createReadStream | 流式读取 |
// 1.0 引入fs模块
const fs = require('fs')
// 2.0 异步读取
fs.readFile('./天气.txt',(err,data)=>{
if(err){
console.log('读取失败')
return
}
console.log(data.toString()) // 转为utf-8
})
// 3.0 同步读取
let data = fs.readFileSync('./天气.txt')
console.log(data.toString()) // 不转的话是一个buffer
流式读取文件
const fs = require('fs')
// 2.0 创建读取流对象
const rs = fs.createReadStream('./mp4/全世界失眠.m4a')
// 3.0 绑定data事件 chunk 块 大块
rs.on('data',(chunk)=>{
//console.log(chunk);// buffer
console.log(chunk.length);//65536 字节 => 64kb
})
// 4.0 可选事件 end
rs.on('end',()=>{
console.log('读取完成')
})
练习:拷贝我们刚才的音频
const fs = require('fs')
const process = require('process')
// 方式一 用readFile
// 1.0 读取文件
let data =fs.readFileSync('./mp4/全世界失眠.m4a')
// 2.0 写入文件
fs.writeFileSync('./mp4/全世界失眠2.m4a',data)
// 打印内存占用量
console.log(process.memoryUsage());// rss 34201600 => 32768kb => 32MB
// 方式二 流式操作
// 1.0 创建读取流对象
let rs = fs.createReadStream('./mp4/全世界失眠.m4a')
// 2.0 创建写入流对象
let ws = fs.createWriteStream('./mp4/全世界失眠3.m4a')
// 3.0 绑定事件写入
ws.on('data',chunk=>{
ws.write(chunk)
})
console.log(process.memoryUsage()); // rss 28741632=> 27684kb => 27MB
// 4.0 另外一种写法 pipe 管道
rs.pipe(ws)
5.7文件的移动与重命名
rename 或 renameSync(同步操作)
语法:
fs.rename(oldPath, newPath,callback)
fs.renameSync(oldPath,newPath)
const fs = require('fs')
// 调用rename方法
fs.rename('./天气.txt','./天气预报/天气.txt',err=>{
if(err){
throw err
}
console.log('移动完成')
})
// 注意 文件夹必须存在要不然后会报错
5.8文件删除
unlink 和unlinkSync
语法:
fs.unlink(path,callBack)
fs.unlinkSync(path)
const fs = require('fs')
// 1.0 异步删除
fs.unlink('./你好.txt',err=>{
if(err){
console.log('删除失败')
}
console.log('删除成功')
})
// 2.0 同步删除
let data = fs.unlinkSync('./你好1.txt')
console.log(data) // undefined
// 3.0 14.4版本的新方法 rm 同步 rmSync
fs.rm('./你好2.txt',err=>{
if(err){
console.log('删除失败2')
}
console.log('删除成功2')
})
5.9文件夹操作
可以对文件夹进行 创建、读取、删除等操作
| 方法 | 说明 |
|---|---|
| mkdir / mkdirSync | 创建文件夹 |
| readdir / readdirSync | 读取文件夹 |
| rmdir / rmdirSync | 删除文件夹 |
// 1.0 导入fs模块
const fs = require('fs')
// 2.0 创建 文件夹 mk make 创建 dir directory 文件夹
fs.mkdir('./html',err => {
if(err){
console.log('创建失败',err)
return
}
console.log('创建成功')
})
// 3.0 递归创建 a下面b文件夹下的c文件夹
fs.mkdir('./a/b/c',{recursive: true},err => {
if(err){
console.log('创建失败')
return
}
console.log('创建成功')
})
// 4.0 读取文件夹
// 读取当前文件夹
fs.readdir('./',(err,data)=>{
if(err){
console.log('读取失败')
return
}
console.log(data)
})
fs.readdir('./mp4',(err,data)=>{}) 读取mp4文件夹
// 5.0 删除文件夹
fs.rmdir('./html',err =>{
if(err){
console.log('删除失败')
return
}
console.log('删除成功')
})
// 6.0 递归删除
fs.rmdir('./a',{recursive: true},err =>{
if(err){
console.log('删除失败')
return
}
console.log('删除成功')
})
// 6.1 建议使用 rm删除
fs.rm('./a',{recursive: true},err =>{
if(err){
console.log('删除失败')
return
}
console.log('删除成功')
})
6.0查看资源的状态
const fs = require('fs')
// stat 方法 是status 缩写 状态
fs.stat('./mp4/全世界失眠2.m4a',(err,data)=>{
if(err){
console.log('查看失败')
return
}
console.log(data)
/*
*birthtime 创建时间
* atime 访问时间
* mtime 修改时间
* ctime 最后一次修改状态的时间
* */
// 查看是不是一个文件
console.log(data.isFile()) // true
// 判断是不是一个文件夹
console.log(data.isDirectory()) // false
})
7.0 fs模块路径
// 引入fs模块
const fs = require('fs')
// 相对路径
// 1.0
fs.writeFileSync('./index.html','love')
// 2.0
fs.writeFileSync('index1.html','love')
// 绝对路径
// 1.0 c盘不行 权限不够
fs.writeFileSync('D:/index.html','love')
// 2.0 根路径
fs.writeFileSync('/index.html','love')
相对路径的一些问题
相对路径参照物:是命令行的工作目录
const fs = require('fs')
// 所以用绝对路径 __dirname 绝对路径 “类似全局变量”
// __dirname 保存的是:所在文件的所在目录的绝对路径
console.log(__dirname) // D:\newNode\node-1
fs.writeFileSync(__dirname +'/index2.html','love')
8.0 path模块
path模块提供了操作路径的功能
| API | 说明 |
|---|---|
| path.resolve | 拼接规范的绝对路径常用 |
| path.sep | 获取操作系统的路径分隔符 |
| path.parse | 解析路径并返回对象 |
| path.basename | 获取路径的基础名称 |
| path.dirname | 获取路径的目录名 |
| pathextname | 获取路径的扩展名 |
const fs = require('fs')
// 导入path路径模块
const path = require('path')
// 拼接路径
let url = path.resolve(__dirname,'index.html')
let url1 = path.resolve(__dirname,'./index.html')
console.log(url,url1) // D:\newNode\node-1\index.html D:\newNode\node-1\index.html
// sep 分隔符
console.log(path.sep) // windows下是 \ linux 下是 /
// parse 方法
// __filename 文件的绝对路径
console.log(__filename) // D:\newNode\node-1\3.3path路径.js
let str = "D:\newNode\node-1\3.3path路径.js"
console.log(path.parse(str))
/*{
root: 'D:\',
dir: 'D:\newNode\node-1',
base: '3.3path路径.js',
ext: '.js',
name: '3.3path路径'
}*/
console.log(path.basename(str),path.dirname(str),path.extname(str))
// 3.3path路径.js D:\newNode\node-1 .js
世上的事只要你肯用心学,没有一件会太晚。