关于路径(获取一个绝对路径)
node中除了require的路径是相对于当前文件的路径,其他的都是相对于命令行的路径
const fs = require("fs");
const path = require("path");
path.resolve(__dirname,获取的文件的相对路径); //可以获取这个文件的绝对路径
node中的回调模式
//前面写的是传过去的值content是完成的内容。err是错误
fs.readFile(filename, (*err*, *content*) => {
console.log(*content*);
});
Buffer转换成字符串
fs.readFile(filename, (*err*, *content*) => {
console.log(*content.toString("utf-8")*);
});
关于fs
关于flags
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QZsRgKId-1664767833971)(image-20220509171310229.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-82lS6AIf-1664767833973)(image-20220509171331459.png)]
fs.readFile()读取一个文件
可以传递三个参数第一个是路径,第二个是编码方式,第三个是回调函数,
如果写了编码方式传过来的就不是一个Buffer,就是编码过后的东西
读取文件内容
fs.readFile('/etc/passwd', 'utf8', callback);
fs.writeFile()写入一个文件
如果文件不存在就会新建一个,如果目录不存在就会报错
async function test() {
await fs.promises.writeFile(filename, "dsajkldsa", {
flag: "a",
});
//最后一个表示配置{flag:“a”}表示追加
fs.readFile(filename, (err, content) => {
console.log(content.toString("utf-8"));
});
}
fs.stat()获取文件状态
获取传入文件的状态
也可以传入目录
目录的size为0,目录记录一个指针,指针指向其中文件的地址,打开目录其实是通过指针找到文件的位置
async function test() {
const status = await fs.promises.stat(filename);
console.log(status);
}
test();
//输出结果
Stats {
dev: 1544704498,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 7036874417856700,
size: 47680,
blocks: 96,
atimeMs: 1651996271195.6572,
mtimeMs: 1651718270707.592,
ctimeMs: 1651718270707.592,
birthtimeMs: 1651995922591.119,
atime: 2022-05-08T07:51:11.196Z,
mtime: 2022-05-05T02:37:50.708Z,
ctime: 2022-05-05T02:37:50.708Z,
birthtime: 2022-05-08T07:45:22.591Z
}
fs.readdir()获取文件子目录
获取文件中的子目录
async function test() {
const dirname = path.resolve(__dirname, "./readme");
const paths = await fs.promises.readdir(dirname);
console.log(paths);
}
test();
//输出内容
[ '1.text', 'G.jpg', 'Gf.jpg' ]
fs.mkdir()创建一个目录
可以使用fs.writeFile()创建一个文件
创建一个目录
async function test() {
for (let i = 0; i < 5; i++) {
const dirname = path.resolve(__dirname, `./readme/${i}`);
await fs.promises.mkdir(dirname);
}
}
test();
判断一个一个目录是否存在
async function exits(filename) {
try {
await fs.promises.stat(filename);
return true;
} catch (error) {
if (error.code === "ENOENT") {
return false;
}
throw error;
}
}
async function test() {
const dirname = path.resolve(__dirname, "./readme/7");
const result = await exits(dirname);
if (result) {
console.log("目录已存在");
} else {
console.log("目录不存在,已经帮你创建");
fs.promises.mkdir(dirname);//c
}
}
test();
fs.unlink()删除一个文件
删除一个文件
fs.unlink(filename)
关于path
path.basename()获得文件名
得到这个当前的文件名
async function test() {
const basename = path.basename("/foo/bar/baz/asdf/quux.html");
// Returns: 'quux.html'
console.log(basename);
}
path.sep 操作系统分隔符
path.sep就是当前操作系统的分隔符
console.log(path.sep);
/
path.delimiter 系统之间的分隔符
path.delimiter是系统之间的分隔符
console.log(path.delimiter);
:
path.dirname()获得当前目录
获取当前的目录
async function test() {
const dirname = path.dirname("/foo/bar/baz/asdf/quux");
console.log(dirname);
///foo/bar/baz/asdf
}
path.extname()获取当前的文件类型(.js、.html)
获取当前的文件类型
async function test() {
const extname = path.extname("/foo/bar/baz/asdf/quux.html");
console.log(extname);
//.html
}
path.join()把所有传进去的路径合起来
把所有传进去的路径合起来
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// Returns: '/foo/bar/baz/asdf'
path.resolve()把传进去的路径合起来
把传进去的路径合起来
path.resolve('/foo/bar', './baz');
// Returns: '/foo/bar/baz'
关于IO流
fs.createReadStream()创建一个可读流
创建一个可读流
//接收两个参数
//文件路径
//配置
const rs = fs.createReadStream(filename, {
encoding: "utf-8",
highWaterMark: 1,//每一次读取的数量,如果encoding===null,就是一个字符,如果是utf-8就是一个文字字符
autoClose:true //完成时自动关闭
});
//使用on函数注册事件
//可以触发的事件
//open 打开之后触发
//error 文件出错了(一般是路径写错了)
//close 文件关闭后触发
//data 只有注册了这个事件才会真正开始读取内容,读取到内容后触发,返回读取到的内容
//end d
//如果要读取全部的数据的话,不如直接用fs.readFile()
//rs.pause() 暂停读取 会触发pause事件
//rs.resume() 恢复读取 会触发resume事件
rs.on("data",chunk=>{
console.log("读取到了文件"+chunk)
}) //只有运行了这个才会开始读取文件不然就不会读取文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TXIs898e-1664767833974)(image-20220509193434726.png)]
fs.createWriteStream()创建一个写入流
const path = require("path");
const fs = require("fs");
const filename = path.resolve(__dirname, "./abc.text");
const ws = fs.createWriteStream(filename, {
flags: "a", //如何对文件进行操作
highWaterMark: 2, //每一次读取的数量,如果encoding===null,就是一个字符,如果是utf-8就是一个文字字符
autoClose: true,
start:1 //起始位置
});
const data = "123456";
ws.write(data);//写入一些数据
//可以穿字符串也可以传buffer,返回一个布尔值(返回的时true的话表示写入通道没有被tian),当写入队列清空时,会触发drain事件
ws.on("open", () => {
console.log("写入开始了");
});
// 注册事件ws.on('事件',callback)
//open事件
//error事件
//close事件
ws.on("close", () => {
console.log("写入结束了");
});
ws.end();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9rxJHVNN-1664767833974)(image-20220509183123451.png)]
ws.write(data)会返回一个布尔值(磁盘的写入速度和内存比是很慢的)当写入通道没满时ws.write(data)会返回true,后面的写入就不用排队可以直接写入,反之就是写入通道被占满了,接下来的数据会进入写入队列
背压问题:
造成原因:内存速度太快了,但是磁盘写入很慢,很多要写入的东西都积压在写入队列,造成很大的内存空间占用。因为写入队列是内存中的数据,是有限的,可以使用drain事件来解决这个问题,这个事件会在当原来是满的时候,当写入队列清空时,会触发drain事件,如果本来就没有满,就算清空了也不会触发事件
防止背压的写入方法
async function method2() {
const from = path.resolve(__dirname, "./abc.text");
const to = path.resolve(__dirname, "./cba.text");
const rs = fs.createReadStream(from);
const ws = fs.createReadStream(to);
(rs.on("data", (chunk) => {
const flag = ws.write(chunk);
if (!flag) {
rs.pause();
}
});
ws.on("drain", () => {
rs.resume();
});)//可以简写为rs.pipe(ws)
}
//直接使用rs.pipe(ws)就可以完成上面的操作
net模块(通信模块)
利用net模块已经进行进程之间的通信(IPC协议)
前端主要是网络协议(TCP/IP协议 )
创建客户端
net.createConnection(options[, connectListener])
const net = require("net");
//第一个参数是配置项,第二个就是连接成功之后的回调函数
net.createConnection(
{
host: "xxx.xxx.xxx",
port: 80,
},
() => {
console.log("连接成功");
}
);
截取请求头内容
function parseResponse(response) {
const index = response.indexOf("\r\n\r\n"); //获取请求头的结束index
const head = response.substring(0, index); //截取请求头部分
const body = response.substring(index + 2); //截取请求体部分
const headParts = head.split("\r\n"); //把请求头以换行作为分隔符拆分为数组
const headerArray = headParts.slice(1).map(str => {
return str.split(":").map(s => s.trim());
});
const header = headerArray.reduce((a, b) => {
a[b[0]] = b[1];
return a;
}, {});
return {
header, //请求头
body: body.trimStart() //请求体
};
}
创建一个服务器
const net = require("net");
const server = net.createServer();
server.listen(9258); //监听某个端口
server.on("listening", () => {}); //开始监听端口后触发的事件
server.on("connection", (socket) => {
socket.on("data", function (thunk) {
console.log(thunk.toString("utf-8"));
//这里有个http响应格式规范
//响应头的响应体换两行
socket.write(`HTTP/1.1 200 OK
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
width: 0;
height: 0;
border: 10px solid red;
border-right-color: transparent;
border-bottom: transparent;
border-left: transparent;
transform: rotate(45deg);
}
</style>
</head>
<body>
<div></div>
</body>
</html>
`);
socket.end();
});
socket.on("close", function () {
console.log("连接关闭了");
});
}); //在某个连接到来时,触发的事件
传输一个图片
const net = require("net");
const server = net.createServer();
const fs = require("fs");
const path = require("path");
server.listen(9258); //监听某个端口
server.on("listening", () => {}); //开始监听端口后触发的事件
server.on("connection", (socket) => {
socket.on("data", async function (thunk) {
//这里有个http响应格式规范
//响应头的响应体换两行
//传输一个图片
const filename = path.resolve(__dirname + "/1.jpg");
console.log(filename);
const bodyBuffers = await fs.promises.readFile(filename);
const headerBuffers = Buffer.from(`HTTP/1.1 200 OK
Content-Type:image/jpeg
`,
"utf-8"
);
const result = Buffer.concat([headerBuffers, bodyBuffers]);
socket.write(result);
socket.end();
});
socket.on("close", function () {
console.log("连接关闭了");
});
}); //在某个连接到来时,触发的事件
http模块
发送请求(post/get)
const http = require("http");
const request = http.request(
"http://yuanjin.tech:5005/api/movie",
{
method: "POST",
},
(resp) => {
let result = "";
console.log("响应的请求头", resp.headers);
resp.on("data", (thunk) => {
result += thunk;
});
resp.on("end", () => {
console.log(JSON.parse(result));
});
}
);
request.write("a=1&b=2"); //发送post请求携带的参数(写在消息体里面) get的话直接发就行
//这个request对象就是一个可写流
request.end(); //end之后才会真正的获取相应 因为请求中没有两次换行所以服务器认为还有东西没有发送,所以调用end之后才会真正的获取响应(表示消息体结束)
创建一个服务器
const http = require("http");
const url = require("url");
const server = http.createServer((req, resp) => {
//req incomingMessage (发送请求过来的那个对象)
//res serverResponse (用于响应的)
console.log("请求路径", url.parse(req.url)); //利用url模块解析发送请求的地址
console.log("请求方法", req.method);
console.log("请求头", req.headers);
let body = "";
req.on("data", (thunk) => {
//请求体要从流里面读,因为可能请求的东西很多,放在配置里面就会占用很多内存,所以要一块一块传(配置里面的东西也都会放在内存里)
body += thunk.toString("utf-8");
});
req.on("end", () => {
console.log("请求体", body);
});
resp.setHeader("a", "1"); //设置响应头
resp.setHeader("b", "2");
resp.write("hello"); //响应的数据
resp.end(); //一定要写 结束响应
});
server.listen(9527);
server.on("listening", () => {
console.log("server listening 9527");
});
搭建一个静态资源服务器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YdzDaP9y-1664767833975)(image-20220609142640461.png)]
const http = require("http");
const URL = require("url");
const path = require("path");
const fs = require("fs");
async function getStat(filename) {
try {
return await fs.promises.stat(filename);
} catch (error) {
return null;
}
}
/**
*
* @param {*} url
* @returns 得到文件内容
*/
async function getFileContent(url) {
const urlObj = URL.parse(url);
let filename;
filename = path.resolve(__dirname, "public", urlObj.pathname.substring(1)); //如果不用substring的话就会定位到根目录,因为urlObj.pathname有一个/
// console.log(urlObj);
let stat = await getStat(filename);
if (!stat) {
//文件不存在
console.log("文件不存在");
return null;
} else if (stat.isDirectory()) {
//文件是一个目录
console.log("自动添加index.html");
filename = path.resolve(
__dirname,
"public",
urlObj.pathname.substring(1),
"index.html"
);
console.log(filename);
stat = await getStat(filename);
if (!stat) {
console.log("文件不存在");
return null;
} else {
console.log("正常文件");
console.log(filename);
return await fs.promises.readFile(filename); //返回文件建议使用流的方式返回
}
} else {
console.log("正常的文件");
console.log(filename);
return await fs.promises.readFile(filename); //返回文件建议使用流的方式返回
}
}
async function handler(req, resp) {
const info = await getFileContent(req.url);
if (info) {
resp.write(info);
} else {
resp.statusCode = 404;
resp.write("Resource is not exist");
}
resp.end();
}
const server = http.createServer(handler);
server.listen(6100);
server.on("listening", () => {
console.log("server listening 6000");
});