NodeJS

Buffer

概念

Buffer是一个类似于数组的对象,用于表示固定长度的字节序列

Buffer本质是一段内存空间,专门用来处理二进制数据

特点

  1. Buffer大小固定且无法调整
  2. Buffer性能较好,可以直接对计算机内存进行操作
  3. 每个元素的大小为1字节(byte)

使用

创建Buffer

1
2
3
4
5
6
7
8
9
10
11
//创建了一个长度为 10 字节的 Buffer,相当于申请了 10 字节的内存空间,每个字节的值为 0
let buf = Buffer.alloc(10); // 结果为 <Buffer 00 00 00 00 00 00 00 00 00 00>

//创建了一个长度为 10 字节的 Buffer,buffer 中可能存在旧的数据, 可能会影响执行结果,所以叫 unsafe
let buf1 = Buffer.allocUnsafe(10000);

//通过字符串创建 Buffer
let buf2 = Buffer.from('hello');

//通过数组创建 Buffer
let buf3 = Buffer.from([105, 168, 1231, 1, 516]);

Buffer与字符串的转化

可以借助toString方法将Buffer转为字符串

1
2
let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);
console.log(buf_4.toString()) // iloveyou

Buffer的读写

Buffer可以直接通过[]的方式对数据进行处理。

1
2
3
4
5
6
7
// 读取
console.log(buf1[1]);
console.log(buf1[1].toString(2)); // 注意,这个toString的方法是用来将数据转为二进制(因为传参2)进行显示
// 修改
buf1[1] = 97;
//查看字符串结果
console.log(buf1.toString());

注意:如果修改的数值超过255,则超过8位数据会被舍弃

一个uff-8的字符一般占3个字节

fs模块

fs全称为file system,称之为文件系统,是Node.js中的内置模块,可以对计算机中的磁盘进行操作。

文件写入

文件写入就是将数据保存到文件当中。

方法 说明
writeFile 异步写入
writeFileSync 同步写入
appendFile / appendFileSync 追加写入
createWriteStream 流式写入

writeFile异步写入

语法:

1
fs.writeFile(file, data[, options], callback)

参数说明

  1. file 文件名
  2. data 待写入的数据
  3. options 选项设置(可选)
  4. callback 写入回调

返回值:undefined

代码示例:

1
2
3
4
5
6
7
8
9
10
11
// require 是 Node.js 环境中的'全局'变量,用来导入模块
const fs = require('fs');
//将 『三人行,必有我师焉。』 写入到当前文件夹下的『座右铭.txt』文件中
fs.writeFile('./座右铭.txt', '三人行,必有我师焉。', err => {
//如果写入失败,则回调函数调用时,会传入错误对象,如写入成功,会传入 null
if(err){
console.log(err);
return;
}
console.log('写入成功');
});

writeFileSync同步写入

语法:

1
fs.writeFileSync(file, data[, options])

参数与fs.writeFile大体一致,只是没有callback参数

返回值:undefined

代码示例:

1
2
3
4
5
try{
fs.writeFileSync('./座右铭.txt', '三人行,必有我师焉。');
} catch(e){
console.log(e);
}

Node.js中的磁盘操作是由其他线程完成的,结果的处理有两种模式

  1. 同步处理 javascript主线程会等待其他线程的执行结果,然后再继续执行主线程的代码
  2. 异步处理 javascript主线程不会等待其他线程的执行结果,直接执行后续的主线程代码

appendFile / appendFileSync追加写入

appendFile作用是在文件尾部追加内容,appendFile语法于writeFile语法完全相同

语法:

1
2
fs.appendFile(file, data[, options], callback)
fs.appendFileSync(file, data[, options])

返回值:二者都会undefined

示例代码:

1
2
3
4
5
fs.appendFile('./座右铭.txt','择其善者而从之,其不善者而改之。', err => {
if(err) throw err;
console.log('追加成功')
});
fs.appendFileSync('./座右铭.txt','\r\n温故而知新, 可以为师矣');

createWriteStream流式写入

语法:

1
fs.createWriteStream(path[, options])

参数说明

  1. path 文件路径
  2. options 选项配置(可选)

返回值:Object

代码示例:

1
2
3
4
5
6
let ws = fs.createWriteStream('./观书有感.txt');
ws.write('半亩方塘一鉴开\r\n');
ws.write('天光云影共徘徊\r\n');
ws.write('问渠那得清如许\r\n');
ws.write('为有源头活水来\r\n');
ws.end();

程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数。

流式写入方式适用于大文件写入或者频繁写入的场景,writeFile适合于写入频率较低的场景。

写入文件的场景

文件写入在计算机中是一个非常常见的操作,下面的场景都用到了文件写入

  1. 下载文件
  2. 安装软件
  3. 保存程序日志,入Git
  4. 编辑器保存文件
  5. 视频录制

当需要持久化保存数据的时候,应该想到文件写入

文件读取

文件读取顾名思义,就是通过程序从文件中取出其中的数据,可以使用如下几种方式:

方法 说明
readFile 异步读取
readFileSync 同步读取
createReadStream 流式读取

readFile异步读取

语法:

1
fs.readFile(path[, options], callback)

参数说明:

  1. path 文件路径
  2. options 选项配置
  3. callback 回调函数

返回值:undefined

示例代码:

1
2
3
4
5
6
7
8
9
10
11
//导入 fs 模块
const fs = require('fs');
fs.readFile('./座右铭.txt', (err, data) => {
if(err) throw err;
console.log(data);
});

fs.readFile('./座右铭.txt', 'utf-8',(err, data) => {
if(err) throw err;
console.log(data);
});

readFileSync同步读取

语法:

1
fs.readFileSync(path[, options])

参数说明:

  1. path 文件路径
  2. options 选项配置

返回值:string | Buffer

代码示例:

1
2
let data = fs.readFileSync('./座右铭.txt');
let data2 = fs.readFileSync('./座右铭.txt', 'utf-8');

createReadStream流式读取

语法:

1
fs.createReadStream(path[, options])

参数说明:

  1. path 文件路径
  2. options 选项配置(可选)

代码示例:

1
2
3
4
5
6
7
8
9
10
11
//创建读取流对象
let rs = fs.createReadStream('./观书有感.txt');
//每次取出 64k 数据后执行一次 data 回调
rs.on('data', data => {
console.log(data);
console.log(data.length);
});
//读取完毕后, 执行 end 回调
rs.on('end', () => {
console.log('读取完成')
})

读取文件应用场景

  1. 电脑开机
  2. 程序运行
  3. 编辑器打开文件
  4. 查看图片
  5. 播放视频
  6. 播放音乐
  7. Git查看日志
  8. 上传文件
  9. 查看聊天记录

文件移动与重命名

在Node.js中,我们可以使用rename或renameSync来移动或重命名文件或文件夹

语法:

1
2
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)

参数说明:

  1. oldPath 文件当前的路径
  2. newPath 文件新的路径
  3. callback 操作后的回调

代码示例:

1
2
3
4
5
fs.rename('./观书有感.txt', './论语/观书有感.txt', (err) =>{
if(err) throw err;
console.log('移动完成')
});
fs.renameSync('./座右铭.txt', './论语/我的座右铭.txt');

文件删除

在Node.js中,我们可以使用unlink、unlinkSync、rm、rmSync来删除文件

语法:

1
2
3
4
fs.unlink(path, callback)
fs.unlinkSync(path)
fs.rm(path, callback)
fs.rmSync(path)

参数说明:

  1. path 文件路径
  2. callback 操作后的回调

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
const fs = require('fs');
fs.unlink('./test.txt', err => {
if(err) throw err;
console.log('删除成功');
});
fs.unlinkSync('./test2.txt');

fs.rm('./test.txt', err => {
if(err) throw err;
console.log('删除成功');
});
fs.rmSync('./test2.txt');

文件夹操作

借助Node.js的能力,可以对文件夹进行创建、读取、删除等操作

方法 说明
mkdir / mkdirSync 创建文件夹
readdir / readdirSync 读取文件夹
rmdir / rmdirSync 删除文件夹

创建文件夹

语法:

1
2
fs.mkdir(path[, options], callback)
fs.mkdirSync(path[, options])

参数说明:

  1. path 文件夹路径
  2. options 选项配置(可选)
  3. calback 操作后的回调

示例代码:

1
2
3
4
5
6
7
8
9
10
11
fs.mkdir('./page', err => {
if(err) throw err;
console.log('创建成功');
});
//递归异步创建,如果不传recursive这个参数,那么就会报错
fs.mkdir('./1/2/3', {recursive: true}, err => {
if(err) throw err;
console.log('递归创建成功');
});
//递归同步创建文件夹
fs.mkdirSync('./x/y/z', {recursive: true});

读取文件夹

语法:

1
2
fs.readdir(path[, options], callback)
fs.readdirSync(path[, options])

参数说明:

  1. path 文件夹路径
  2. options 选项配置(可选)
  3. callback 操作后的回调

示例代码:

1
2
3
4
5
6
7
8
//异步读取
fs.readdir('./论语', (err, data) => {
if(err) throw err;
console.log(data);
});
//同步读取
let data = fs.readdirSync('./论语');
console.log(data);

删除文件夹

语法:

1
2
fs.rmdir(path[, options], callback)
fs.rmdirSync(path[, options])

参数说明:

  1. path 文件夹路径
  2. options 选项配置(可选)
  3. callback 操作后的回调

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//异步删除文件夹
fs.rmdir('./page', err => {
if(err) throw err;
console.log('删除成功');
});
//异步递归删除文件夹
fs.rmdir('./1', {recursive: true}, err => {
if(err) {
console.log(err);
}
console.log('递归删除')
});
//同步递归删除文件夹
fs.rmdirSync('./x', {recursive: true})

查看资源状态

在Node.js中,可以使用stat或statSync来查看资源的详细信息

语法:

1
2
fs.stat(path[, options], callback)
fs.statSync(path[, options])

参数说明:

  1. path 文件夹路径
  2. options 选项配置(可选)
  3. callback 操作后的回调

示例代码:

1
2
3
4
5
6
7
//异步获取状态
fs.stat('./data.txt', (err, data) => {
if(err) throw err;
console.log(data);
});
//同步获取状态
let data = fs.statSync('./data.txt');

结果值对象结构:

  1. size 文件体积
  2. birthtime 创建时间
  3. mitime 最后修改时间
  4. isFile 检测是否为文件
  5. isDirectory 检测是否为文件夹

__dirname

__dirname与require类似,都是Node.js环境中的’全局变量’

__dirname保存着当前文件所在目录的绝对路径,可以使用__dirname与文件名拼接成绝对路径

代码示例:

1
2
let data = fs.readFileSync(__dirname + '/data.txt');
console.log(data);

path模块

path模块提供了操作路径的功能,如下为几个常用的API:

API 说明
path.resolve 拼接规范的绝对路径
path.sep 获取操作系统的路径分隔符
path.parse 解析路径并返回对象
path.basename 获取路径的基础名称
path.dirname 获取路径的目录名
path.extname 获取路径的扩展名

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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));

HTTP协议

一、概念

HTTP(hypertext transport protocol)协议;中文叫超文本传输协议

是一种基于TCP/IP的应用层通信协议

这个协议详细规定了浏览器和万维网服务器之间互相通信的规则

协议中主要规定了两个方面的内容

  1. 客户端:用来向服务器发送数据,可以被称之为请求报文
  2. 服务端:向客户端返回数据,可以被称之为响应报文

报文:可以简单理解为就是一堆字符串

二、请求报文的组成

  1. 请求行
  2. 请求头
  3. 空行
  4. 请求体

三、HTTP的请求行

  1. 请求方法(get、post、put、delete等)
  2. 请求URL(统一资源定位器)
    1. 例如:http://www.baidu.com:80/index.html?a=100&b=200#logo
      1. http:协议(https、ftp、ssh等)
      2. www.baidu.com 域名
      3. 80 端口号
      4. /index.html 路径
      5. a=100&b=200 查询字符串
      6. #logo 哈希(锚点链接)
  3. HTTP协议版本号

四、HTTP请求头

格式:【头名:头值】

常见的请求头有:

请求头 解释
Host 主机名
Connection 链接的设置 keep-alive(保持连接);close(关闭连接)
Cache-Control 缓存控制 max-age = 0 (没有缓存)
Upgrade Insecure Requests 将网页中的http请求转化为https请求(很少用)老网站升级
User-Agent 用户代理,客户端字符串标识,服务器可以通过这个标识来识别这个请求来自 哪个客户端 ,一般在PC端和手机端的区分
Accept 设置浏览器接收的数据类型
Accept-Encoding 设置接收的压缩方式
Accept Language 设置接收的语言 q=0.7 为喜好系数,满分为1
Cookie

五、HTTP请求体

请求体内容的格式是非常灵活的

(可以是空)==> GET请求

(也可以是字符串,还可以是JSON) ===> POST请求

六、响应报文的组成

  1. 响应行
    1. HTTP/1.1 200 OK
      1. HTTP/1.1:HTTP协议版本号
      2. 200:响应状态码 404 Not Found 500 Internal Server Error
      3. OK:响应状态描述
  2. 响应头
    1. Cache-Control:缓存控制 private 私有的,只允许客户端缓存数据
    2. Connection 链接设置
    3. Content-Type:text/html;charset=utf-8 设置响应体的数据类型以及字符集,响应体为html,字符集utf-8
    4. Content-Length:响应体的长度,单位为字节
  3. 空行
  4. 响应体

响应体内容的类型是非常灵活的,常见的类型有HTML、CSS、JS、图片、JSON

七、创建HTTP服务

使用Node.js创建HTTP服务

操作步骤