简单的说 Node.js 就是运行在服务端的 JavaScript。
Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。
Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。
Node.js 只支持JavaScript
练习
创建一个index.js文件
console.log('Hello world! -----> ');
function test(){
console.log('test -----> ');
}
test()
setTimeout(() => {
console.log(' -----> world' );
},1000)
setInterval(() => {
console.log(' -----> wo' );
},1000)
console.log('global -----> ');
console.log('globalThis -----> ');
运行
node .index.js
技巧,写一个i开头按tab键自动补全即可运行
总结
1.node.js中不能使用Bom和Dom的API,可以使用consloe和定时器API
2.node.js中的顶级对象为global,也可以用glovalThis访问顶级对象
cmd常用命令
|切换盘符|c: D:
|切换工作目录|cd
|查看目录文件|dir
|查看所有目录|dir /s
Node.js Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。
// 1.alloc
let buf =Buffer.alloc(10)
// console.log('buf -----> ', buf);
// 2.allocUnsafe
let buf2=Buffer.allocUnsafe(1000)
// console.log('buf2 -----> ', buf2);
// 3.from
let buf_3=Buffer.from('hello')
let buf_4=Buffer.from([105,108,111,102,125])
//console.log('buf_4 -----> ', buf_4);
// 转字符串
let buf_5=Buffer.from([105,108,111,118,101,121,111,117])//utf-8
console.log(buf_5.toString());//输出iloveyou
Node.js 目前支持的字符编码包括:
- ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
- utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
- utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
- ucs2 - utf16le 的别名。
- base64 - Base64 编码。
- latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
- binary - latin1 的别名。
- hex - 将每个字节编码为两个十六进制字符。
创建 Buffer 类
Buffer 提供了以下 API 来创建 Buffer 类:
- Buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0
- Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据
- Buffer.allocUnsafeSlow(size)
- Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)
- Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。
- Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例
- Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');
// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
fs模块
以下fs模块操作都是为了实现自动化
写入文件
writeFile异步写入
/* 学习目标:文件写入fs
需求:新建一个文件,右铭.txt,写入内容
*/
// 1.导入fs 模块
const fs=require('fs')
// 2.写入文件
fs.writeFile('./右铭.txt','天天向上',err=>{
if(err){
console.log(' -----> 写入失败 ' );
return
}
console.log(' -----> 写入成功 ' );
})
同步写入
// 1.导入fs 模块
const fs=require('fs')
fs.writeFileSync('./data.txt','hello')
推荐用异步写入
追加文件写入
// 1.引入模块
const fs=require('fs')
// 2.调用appendFile
// 异步追加
fs.appendFile('./右铭.txt','吱吱吱',err=>{
if(err){
console.log(' -----> 追加失败 ') ;
return
}
console.log(' -----> 追加成功 ');
})
// 1.引入模块
const fs=require('fs')
// 3.
// 同步追加 rn:换行
fs.appendFileSync('./右铭.txt','rn我喜欢你')
// 1.引入模块
const fs=require('fs')
// 4.writeFile 实现追加写入
// w=写入模式 a=追加模式 r=读取模式
fs.writeFile('./右铭.txt','love love love',{flag:"a"},err=>{
if(err){
console.log(' -----> 追加失败 ') ;
return
}
console.log(' -----> 追加成功 ');
})
w=写入模式,a=追加模式,r=读取模式
文件流式写入
// 1.导入fs
const fs=require('fs')
// 2创建写入对象
const ws=fs.createWriteStream('./诗句.txt')
// 3.write
ws.write("床前明月光rn")
ws.write("疑是地上霜rn")
ws.write('举头望明月rn')
ws.write("低头思故乡rn")
// 4.关闭通道 (可选)
ws.close()
rn表示换行
程序打开一个文件是需要消耗资源的,流式布局可以减少打开关闭文件的次数。
流式写入方式适用于 大文件写入或者频繁写入 的场景,writerFile适用于 写入频繁较低的场景
文件写入
文件写入 在计算机中是一个非常常见的操作,下面的场景都用到了文件写入
-
下载文件
-
安装软件
-
保存程序日志,如 Git
-
编辑器保存文件
-
视频录制
当 需要持久化保存数据 的时候,应该想到 文件写入
二、文件读取
文件读取顾名思义,就是通过程序从文件中取出其中的数据,我们可以使用如下几种方式:
方法 | 说明 |
---|---|
readFile | 异步读取 |
readFileSync | 同步读取 |
createReadStream | 流式读取 |
readFile 读取
1. readFile 异步读取
语法: fs.readFile(path[, options], callback)
参数说明:
path 文件路径
options 选项配置(可选)
callback 回调函数
返回值: undefined
代码示例:
// 1.导入fs
const fs=require('fs')
// 2.异步读取
fs.readFile('./诗句.txt',(err,data)=>{
if(err){
console.log(' -----> 读取失败');
return
}
console.log(data.toString());
})
2.readFileSync 同步读取
语法: fs.readFileSync(path[, options])
参数说明:
path 文件路径
options 选项配置
返回值: string | Buffer
代码示例:
同步读取
// 3.同步读取
let data=fs.readFileSync('./诗句.txt')
console.log(data.toString());
createReadStream 流式读取
语法: fs.createReadStream(path[, options])
参数说明:
path 文件路径
options 选项配置( 可选 )
返回值: Object
代码示例:
//创建读取流对象
let rs = fs.createReadStream('./观书有感.txt');
//每次取出 64k 数据后执行一次 data 回调
rs.on('data', data => {
console.log(data);
console.log(data.length);
});
//读取完毕后, 执行 end 回调
//emd(可选)
rs.on('end', () => {
console.log('读取完成')
})
文件复制————练习
先读取再写入,两种方式
方式一:
const fs=require('fs')
// 方式一 readFile
// 读取文件内容
let data=fs.readFileSync('./诗句.txt')
// 写入文件
fs.writeFileSync('./诗句2.txt',data)
方式二:
const fs=require('fs')
// 流式操作👍推荐使用
// 创建读取
const rs=fs.createReadStream('./诗句.txt')
// 创建写入
const ws=fs.createWriteStream('./诗句3.txt')
// 简写事件
rs.pipe(ws)
优先推荐使用流式布局,因为流式布局占用64kb,传输的文件比较小
文件移动与重命名
在 Node.js 中,我们可以使用 rename 或 renameSync 来移动或重命名 文件或文件夹
语法:
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)
参数说明:
oldPath 文件当前的路径
newPath 文件新的路径
callback 操作后的回调
代码示例
重命名:
const fs=require('fs')
// 调用 rename方法
fs.rename('./原神.txt','./启动.txt',err=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 失败' );
})
移动文件:
fs.rename('./启动.txt','../资料/原神.txt',err=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 失败' );
})
文件删除
在 Node.js 中,我们可以使用 unlink 或 unlinkSync 来删除文件
语法:
fs.unlink(path, callback)
fs.unlinkSync(path)
参数说明:
path 文件路径
callback 操作后的回调
代码示例:
const fs=require('fs')
//调用unlink方法
fs.unlink('./诗句3.txt',err=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 成功');
})
或者node.js14.4引入的新方法rm
// 2.调用rm方法 14.4
fs.rm('./诗句3.txt',err=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 成功');
})
文件夹操作
借助 Node.js 的能力,我们可以对文件夹进行 创建 、 读取 、 删除 等操作
方法 | 说明 |
---|---|
mkdir / mkdirSync | 创建文件夹 |
readdir / readdirSync | 读取文件夹 |
rmdir / rmdirSync | 删除文件夹 |
mkdir 创建文件夹
在 Node.js 中,我们可以使用 mkdir 或 mkdirSync 来创建文件夹
语法:
fs.mkdir(path[, options], callback)
fs.mkdirSync(path[, options])
参数说明:
path 文件夹路径
options 选项配置( 可选 )
callback 操作后的回调
示例代码:
//异步创建文件夹
const fs = require('fs');
fs.mkdir('./html',err=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 创建成功' );
})
// 递归创建
fs.mkdir('./a/b/c',{recursive:true},err=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 创建成功' );
})
readdir 读取文件夹
在 Node.js 中,我们可以使用 readdir 或 readdirSync 来读取文件夹
语法:
fs.readdir(path[, options], callback)
fs.readdirSync(path[, options])
参数说明:
path 文件夹路径
options 选项配置( 可选 )
callback 操作后的回调
示例代码
// 同步读取文件夹
fs.readdir('./',(err,data)=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 读取成功',data );
})
//同步读取
let data = fs.readdirSync('./论语');
console.log(data);
删除文件夹
rmdir 删除文件夹
在 Node.js 中,我们可以使用 rmdir 或 rmdirSync 来删除文件夹
语法:
fs.rmdir(path[, options], callback)
fs.rmdirSync(path[, options])
参数说明:
path 文件夹路径
options 选项配置( 可选 )
callback 操作后的回调
示例代码:
//异步删除文件夹
fs.rmdir('./page', err => {
if(err) throw err;
console.log('删除成功');
});
//异步递归删除文件夹 👍推荐使用rm
fs.rm('./1', {recursive: true}, err => {
if(err) {
console.log(err);
}
console.log('递归删除')
});
//同步递归删除文件夹
fs.rmdirSync('./x', {recursive: true})
查看资源状态
在 Node.js 中,我们可以使用 stat 或 statSync 来查看资源的详细信息
语法:
fs.stat(path[, options], callback)
fs.statSync(path[, options])
参数说明:
path 文件夹路径
options 选项配置( 可选 )
callback 操作后的回调
示例代码:
const fs=require('fs')
fs.stat('./02.index.js',(err,data)=>{
if(err){
console.log(' -----> 失败' );
return
}
console.log(' -----> 成功' ,data);
console.log(' -----> 成功' ,data.size);
})
结果值对象结构:
size 文件体积
birthtime 创建时间
mtime 最后修改时间
isFile 检测是否为文件
isDirectory 检测是否为文件夹
相对路径问题
fs 模块对资源进行操作时,路径的写法有两种:
相对路径
./座右铭.txt 当前目录下的座右铭.txt
座右铭.txt 等效于上面的写法
../座右铭.txt 当前目录的上一级目录中的座右铭.txt
绝对路径
D:/Program Files windows 系统下的绝对路径
/usr/bin Linux 系统下的绝对路径
相对路径中所谓的 当前目录 ,指的是 命令行的工作目录 ,而并非是文件的所在目录
所以当命令行的工作目录与文件所在目录不一致时,会出现一些 BUG
const fs=require('fs')
// 相对路径
fs.writeFileSync('./index.html','love')
fs.writeFileSync('../index.html','love')
// 绝对路径
fs.writeFileSync('D:/index.html','love')
// 写c盘会失败,因为权限不足
__dirname
__dirname 与 require 类似,都是 Node.js 环境中的'全局'变量
__dirname 保存着 当前文件所在目录的绝对路径 ,可以使用 __dirname 与文件名拼接成绝对路径
代码示例:
使用 fs 模块的时候,尽量使用 __dirname 将路径转化为绝对路径,这样可以避免相对路径产生的
Bug
const fs=require('fs')
// 绝对路径 "全局变量" 保存的是:所在文件的所有目录的绝对路径
console.log('----->', __dirname);
const filePath = `${__dirname}/index.html`;
fs.writeFileSync(filePath, 'love');
path 模块
path 模块提供了 操作路径 的功能,我们将介绍如下几个较为常用的几个 API:
API | 说明 |
---|---|
path.resolve | 拼接规范的绝对路径 常用 |
path.sep | 获取操作系统的路径分隔符 |
path.parse | 解析路径并返回对象 |
path.basename | 获取路径的基础名称 |
path.dirname | 获取路径的目录名 |
path.extname | 获得路径的扩展名 |
代码示例:
const fs=require('fs');
const path = require('path');
// resolve 解决
console.log(path.resolve(__dirname,'./index.html') );
const path = require('path');
//获取路径分隔符
console.log(path.sep);
//拼接绝对路径
console.log(path.resolve(__dirname, 'test'));
//解析路径
let pathname = 'D:/program file/nodejs/node.exe';
console.log(path.parse(pathname));
//获取路径基础名称
console.log(path.basename(pathname))
//获取路径的目录名
console.log(path.dirname(pathname));
//获取路径的扩展名
console.log(path.extname(pathname));