Path模块
处理文件路径的小工具
引入:
var path = require("path")
1、解析后缀名
path.extname(p)
- 返回路径中文件的后缀名,即路径中最后一个’.'之后的部分。如果一个路径中并不包含’.‘或该路径只包含一个’.’> 且这个’.'为路径的第一个字符,则此命令返回空字符串。
- 如果在使用之前的mime匹配标准格式则为:
let path = require('path');
let mime = require('./mime.json')
module.exports = () => {
//1. 解析后缀名
let pathname = "test.json";
let pathnamem = "test.jpg";
let a = path.extname(pathname);
let b = path.extname(pathnamem);
console.log(a, b);//.json .jpg
let c = mime[a];
let d = mime[b];
console.log(c, d);// application/json image/jpeg
}
2、文件名连接
该方法的主要用途在于,会正确使用当前系统的路径分隔符
path.join([path1][, path2][, ...])
示例:
// 2. join
let pathname = path.join('public','test','test2');
console.log(pathname);// public\test\test2
3、绝对路径
path.resolve([from ...], to)
将 to 参数解析为绝对路径,给定的路径的序列是从右往左被处理的,后面每个 path 被依次解析,直到构造完成一个绝对路径。
百度后了解到,join
是拼接给定参数形成路径,而resolve类似cd
let c = path.resolve('/foo/bar', './baz');
console.log(c); // D:\foo\bar\baz
let b = path.resolve('/foo/bar', '/tmp/file/');
console.log(b);// D:\tmp\file
let a =
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
console.log(a);// D:\node\Mystudy1\wwwroot\static_files\gif\image.gif
4、basename
path.basename(p)
返回路径中的最后一部分。
let a= path.basename("public/zmtTest/addfile");
console.log(a);//addfile
5、path.parse(pathString)
字符串转对象
let a= path.parse("public/zmtTest/addfile");
console.log(a);
//输出结果如下:
{ root: '',
dir: 'public/zmtTest',
base: 'addfile',
ext: '',
name: 'addfile' }
Stream流
- Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个> Stream,还有
stdout
(标准输出)。- 所有的 Stream 对象都是
EventEmitter
的实例。
- 四种流类型:
Readable
- 可读操作。
Writable
- 可写操作。
Duplex
- 可读可写操作.
Transform
- 操作被写入数据,然后读出结果。
- 常用的事件有:
data
- 当有数据可读时触发。
end
- 没有更多的数据可读时触发。
error
- 在接收和写入过程中发生错误时触发。
finish
- 所有数据已被写入到底层系统时触发。
从流中读取数据示例
- 步骤
- 创建 可读 流
- 设置编码为
utf8
- 处理流事件 -->
data, end, and error
- 文件目录如下:
- 具体代码:
- 主文件为app.js文件
const http = require('http');
let server = require('./models/server');
http.createServer(server).listen(8080, "localhost", () => {
console.log("——————本机端口号: http://127.0.0.1:8080————————");
})
cnpm init
创建package.json
文件,手动建立node_modules
文件夹- 新建
models
目录封装模块,其中,server.js
文件同之前一样:
const url = require('url');
let stream=require('./stream')
module.exports = (req, res) => {
let path = url.parse(req.url);
if (path.pathname != "/favicon.ico") {
res.writeHead(200, { "Content-Type": "text/html;charset=utf-8" });
//加载其他模块
stream();
res.write("首页");
res.end();
}
}
- 再创建数据流模块
//数据流
var fs = require('fs')
module.exports = () => {
var readerstream = fs.createReadStream("public/stu.txt");
var data = '';
readerstream.setEncoding('utf-8');
// 有数据可读时触发。
readerstream.on("data", (res) => {
console.log(data + res);
});
//没有更多的数据可读时触发。
readerstream.on("end", () => {
console.log(data);
});
//在接收和写入过程中发生错误时触发。
readerstream.on("err", () => {
console.log("数据读取失败!");
});
// finish 所有数据已被写入到底层系统时触发。 写入流调用
// readerstream.on("finish", () => {
// console.log("数据读取完成");
// });
}
从流中写入数据示例
- 步骤
要点一:写入数据设置格式不再是直接
setEncoding
,而是.write(data,'UTF8');
要点二:标记文件末尾
- 创建 可写流,写入到文件
out.txt
中 - 设置编码为
utf8
!!! - 标记文件末尾
- 处理流事件 -->
data, end, and error
- 具体代码(只更改了读取数据的核心代码)
var fs = require('fs')
module.exports = () => {
var writestream = fs.createWriteStream("public/out.txt");
var data = '这是一段测试';
// 使用 utf8 编码写入数据
writestream.write(data, 'UTF8');
// 标记文件末尾
writestream.end();
// 处理流事件 --> data, end, and error
writestream.on('finish', () => {
console.log("写入完成。");
});
writestream.on('error', (err) => {
console.log(err.stack);
});
// finish 所有数据已被写入到底层系统时触发。 写入流调用
writestream.on("finish", () => {
console.log("数据读取完成");
});
}
管道流
管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。
我们把文件比作装水的桶,而水就是文件里的内容,我们用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程。
管道流示例
// 管道流 边读边写
let readstream = fs.createReadStream("public/stu.txt");//创建可读流
let writestream = fs.createWriteStream("public/data.txt");//创建可写流
readstream.pipe(writestream);// 读取 stu.txt 文件内容,并将内容写入到 data.txt 文件中
readstream.on("end", () => {
console.log("管道流读取数据完成");
});
writestream.on("finish", () => {
console.log("管道流写入数据完成");
});
非阻塞IO 、阻塞IO
node 里面的非阻塞IO 阻塞IO
fs.readFile();//异步读取文件
fs.readFileSync()//同步读取 阻塞IO
回调函数处理异步 (非阻塞)
var fs=require("fs");
阻塞(同步)请求数据 等待请求完成在执行后续代码
var data=fs.readFileSync("mime.json");
console.log(data.toString());
非阻塞式请求代码 nodejs中多数方法为异步请求方式
fs.readFile("mime.json",function (err,res){
if(err) throw err;
console.log(res.toString());
});
console.log(1);
处理异步请求 外边可以获取到请求的数据的方式
//1.使用回调函数来获取数据
function getMime(callback){
fs.readFile("mime.json",function (err,res){
if(err) throw err;
callback(res.toString());
});
}
console.log(1);
//这样就可以在外部获取异步的数据 也可以暴露出去别的文件使用
module.exports=getMime(function (data){
console.log(data);
});
Node.js EventEmitter
知识点
- Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。
- Node.js 里面的许多对象都会分发事件:一个
net.Server
对象会在每次有新连接时触发一个事件, 一个fs.readStream
对象会在文件被打开的时候触发一个事件。 所有这些产生事件的对象都是events.EventEmitter
的实例。on
函数用于绑定事件函数,emit
属性用于触发一个事件。
使用
在server.js中(文件目录上文中有图)
- 引入 events 模块
var events = require('events');
- 创建 eventEmitter 对象
let eventemit = new events.EventEmitter();
- 在
server.js
中 res.end之前执行方法(传递了一个参数----新建的对象)
event(eventemit);
- 新建event模块,暴露方法
//事件驱动
module.exports = (eventemit) => {
//监听事件驱动
//监听的过程
}
方法
node中,
on
和addListener
没有区别,使用on添加多个事件,后面的事件也不会覆盖之前的事件
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
addListener(event, listener)
为指定事件添加一个监听器
在event.js中:
eventemit.addListener('getjson',()=>{
console.log('事件json 监听函数执行');
});
在server.js
中
setTimeout(() => {
eventemit.emit("getjson");
}, 4000);
on(event, listener)
为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
在event.js中:
eventemit.on('getdata', () => {
console.log('事件一');
});
eventemit.on('getdata', () => {
console.log('事件二');
});
在server.js
中
eventemit.emit("getdata");//不会覆盖第一次
输出为
事件一
事件二
once(event, listener)
为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。
在event.js
中:
eventemit.once('oncetest', () => {
console.log('事件oncetest 监听函数执行');
});
在server.js
中
setTimeout(() => {
eventemit.emit("oncetest");//不执行
}, 4000);
eventemit.emit("oncetest");//输出事件oncetest 监听函数执行
removeListener(event, listener)
移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。
它接受两个参数,第一个是事件名称,第二个是回调函数名称。
let getdatafun=()=>{
console.log('事件一');
}
eventemit.on('getdata',getdatafun);
//事件驱动的方法
eventemit.removeListener('getdata',getdatafun);
removeAllListeners([event])
移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。
eventemit.removeAllListeners();
-
emit(event, [arg1], [arg2], [...])
按监听器的顺序执行执行每个监听器,如果事件有注册监听返回true
,否则返回 false。 -
listeners(event)
返回指定事件的监听器数组。
let es=eventemit.listeners('getdata');
console.log(es);//[ [Function: getdatafun] ]