系统内置模块
模块的分类
- 内置/核心模块
- 用户自定义模块
- 第三方模块
内置/核心模块有:http,fs,path,os,system
核心模块
特点:直接使用,无须下载
他有自己的js文件,只不过被隐藏了
查看内置模块源码:https://github.com/nodejs
FS文件操作
-
使用request 方法加载 fs 核心模块
let fs=require('fs');
-
读取文件readFile [异步读取]
fs.readFile('./one.txt',function(error,data){ if(error){ return error } console.log(data.toString()); });
由于文件操作中使用了错误优先机制,所以回调函数的第一个参数为错误信息
// 1. 使用toString let fs= require('fs'); fs.readFile('./a.txt',function(err,data){ if(err){ console.log('文件请求失败'); return; } console.log(data.toString()) }) // 2. 定义编码格式 let fs= require('fs'); fs.readFile('./a.txt','utf-8',function(err,data){ if(err){ console.log('文件请求失败'); return; } console.log(data) }) // 3. 返回的data数据和字符串进行拼接 let fs= require('fs'); fs.readFile('./a.txt',function(err,data){ if(err){ console.log('文件请求失败'); return; } console.log(data+'') })
最方便的用法就是在输出文件的时候定义编码方式;
-
使用解构赋值,进行简写
var {readFile}=require('fs'); readFile('./one.txt',function(error,data){ console.log(data); console.log(data.toString()); });
-
同步读取文件
let fileData = fs.readFileSync('./test.txt', 'UTF-8'); console.log(fileData);
-
异步写入
// 正常写入
fs.writeFile('./你好.txt', "我们是共产主义接班人...", err=>{
if (err) {
console.log(err);
} else {
console.log("写入成功");
}
});
这样每次写入之后都会把之前的内容给清除掉,并且如果文件不存在,会先创建文件,然后进行写入
// 追加写入
fs.writeFile('test1.txt', "我们是共产主义接班人...", {flag: 'a+'},err=>{
if (err) {
console.log("写入失败");
} else {
console.log("写入成功");
}
});
- 同步写入
// 同步写入
fs.writeFileSync('test1.txt', '该减肥了...', {flag: "a+"});
- 异步追加写入
fs.appendFile('test.txt', '共产党万岁', err=>{
if(!err) {
console.log('异步追加写入成功');
}
});
- 同步追加写入
fs.appendFileSync('test.txt', '世界人大团结万岁!',);
- 异步重命名
fs.rename('test.txt', 'hello.txt', function (err) {
if(!err) {
console.log("异步重命名成功");
}
});
- 异步删除
fs.unlink('test1.txt', function (err) {
if(!err) {
console.log("异步删除成功");
}
});
- 同步删除
fs.unlinkSync('hello.txt');
- stream(流动)-数据流的读取
所谓的数据流,就是数据一部分一部分进行处理,专门用来处理较大的文件,比如:音频,视频,压缩包等;
// 大数据处理 stream 数据流
let fs = require('fs');
// 1, 创建可读流
let redaS = fs.createReadStream('/Users/apple/Desktop/video.zip');
// 2, 创建可写流
let writeS = fs.createWriteStream('./upload.zip');
// 3, 流量检测(每次大约传输67KB)
let num = 0; // 检测文件处理执行的次数
// data:数据处理一部分触发的事件
redaS.on('data', function () {
num++;
});
// 4, 传输结束时回调的方法
// 数据处理完触发的事件
redaS.on('end', function () {
console.log('传输完毕');
console.log(num);
});
// 5, 连接管道
redaS.pipe(writeS);
node的http操作
使用node构建一个web服务器
在node中专门提供了一个核心模块:http;这个模块的职责就是帮你创建便携服务器的
-
加载http模块
let http=require('http'); // 名称一般情况下和模块名保持一致
-
创建web服务器
var serve=http.createServer();
-
注册request请求
serve.on('request',function(){ // request 请求 console.log('收到客服端的请求了'); // 只要服务器发送请求,客户端就能接收到数据 });
-
绑定端口号,启动服务器
serve.listen(8081,function(){ console.log('服务器启动成功了,可以通过http://127.0.0.1:8081来进行访问'); });
-
获取请求中的数据
serve.on('request',function(req, res) { console.log(req.url); // 表示访问路径 console.log(req.headers); // 获取请求头信息 console.log(req.headers["user-agent"]); // 浏览器信息 console.log(req.headers["host"] ); //域名信息 console.log(req.connection.remoteAddress); //表示访问者的ip地址 });
-
Response 获取响应的内容
rep :write 可以用来给客户端发送响应数据;
write可以使用多次,但是最后一次一定要使用end来结束响应,否则客户端会一直等待
end:这个方法是用来告诉服务器,所有的响应头和响应主体已经发送完毕,服务器就会知道这个消息已经完成了。每一个响应消息都必须调用 response.end()
serve.on('request',function(req, res) { // 如果只有write 客户端会一致等待,不会响应数据 res.write('hello'); // 告诉客户端,响应完毕,可以将数据返回给用来 res.end(); res.end('请求结束'); // 里面还可以又结束语 });
-
设置响应头
默认情况下是不支持中文的,需要设置响应头
查看不同类型的相应头:https://tool.oschina.net/commons
// res.setHeader('Content-Type','text/plain;charset=utf-8') // res.setHeader('Content-Type','text/html;charset=utf-8'); serve.on('request',function(req, res) { // 设置响应头(防止出现中文乱码) res.setHeader('content-type', 'text/html;charset=utf-8'); // 如果只有write 客户端会一致等待,不会响应数据 res.write('hello'); // 告诉客户端,响应完毕,可以将数据返回给用来 res.end('请求结束'); // 里面还可以又结束语 });
-
通过url区分访问的内容
var url=req.url; if (url == '/') { res.end("index page"); } else if(url == '/login') { res.end("login page"); } else if(url == '/register') { res.end("register page"); } else { res.end("404 Not Fond"); }
-
模拟一个API的请求
if(url=='/goods'){ var goods=[ { "name":"小米", "price":5799 }, { "name":"锤子", "price":4999 }, { "name":"小辣椒", "price":3999 } ] // 将goods商品全部返回; node不接收数组格式,只能接收string和buffer格式 res.end(goods); res.end(JSON.stringify(goods)); // 返回一个字符串格式就可以了 }
-
请求完整的html页面
方法一:可以直接把页面内容复制过来
// 1.创建一个基础的http请求架构 // 1.加载http模块 let http=require('http'); // 2.创建web服务器 let serve=http.createServer(); // 3.接受请求的内容 serve.on('request',function(req,res){ // / index let url=req.url; if(url=='/'){ // 可以直接把页面内容复制过来 res.end(`<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><h1>首页</h1></body></html>`); } }) // 4.绑定端口号,启动服务器 serve.listen('8080',function(){ console.log('Serve is running'); })
方法二:通过readFile读取文件
serve.on('request',function(req,res){ // index let url=req.url; if(url=='/'){ // 可以直接把页面内容复制过来 // 我们要发送的还是在文件中的内容 fs.readFile('./resource/index.html',function(err,data){ if(err){ res.setHeader('Content-Type','text/plain;charset=utf-8') res.end('文件读取失败,请稍后重试!'); }else{ // data 默认是buffer数据,可以通过toString转为咱们能够识别的字符串 // res.end() 支持两种数据类型,一种是buffer,一种是字符串 res.setHeader('Content-Type','text/html;charset=utf-8') res.end(data); // 如果需要对字符串做处理,可以转格式,我在这就不处理了,直接渲染 } }) } })
-
访问图片
Content-type类型表:https://tool.oschina.net/commons
图片直接访问是访问不出来的,需要添加对应的图片的header头
else if(url=='/shuai'){ // 还是刚才的操作,读取jpg图片,然后再写入res应答中就可以了 fs.readFile('./resource/one.jpg',function(err,data){ if(err){ res.setHeader('Content-Type','text/plain;charset=utf-8') res.end('文件读取失败,请稍后重试!'); }else{ // 失败了还是那样,但是成功了就不一样了 // 图片不需要制定编码方式,我们常说的编码一般指的是字符编码;所以去掉utf8 res.setHeader('Content-Type','image/jpeg') res.end(data); } }) }
解析fs文件操作
fs和http其实就是一个内部js文件,然后在文件的内部有自己的一些成员,咱们在这里只需要引用就可以了;
但是不管是核心模块还是自定义模块 他的使用规则都是一样的; 只不过自定义模块能看到里面的内容,核心模块看不到;
https://github.com/nodejs 查看node源码;核心模块和自定义模块的本质是一样的,都是由各个js文件构成的;
-
获取get请求数据
// 引入模块 let http = require('http'); let {URLSearchParams} = require('url'); var serve = http.createServer(function(req,res){ if(req.url == '/favicon.ico'){ res.send(''); return } // 调用URLSearchParams对象 let parms = new URLSearchParams(req.url.substring(2)); console.log(parms); // 返回所有get数据 console.log(parms.get('username')); // 返货get中的某个值 }); serve.listen(3000,res=>{ console.log('端口号3000'); })
使用parse的简单写法
// 引入模块 let http = require('http'); let {URLSearchParams} = require('url'); var serve = http.createServer(function(req,res){ if(req.url == '/favicon.ico'){ res.send(''); return } // 调用parse获取get参数 let params = url.parse(req.url,true).query; console.log(params); }); serve.listen(3000,res=>{ console.log('端口号3000'); })
案例:使用get请求模拟登陆效果
-
获取post请求数据
获取post请求数据
OS模块的操作
let os=require('os');
// 获取当前汲取的CPU信息
console.log(os.cpus());
// memory 内存
console.log(os.totalmem());
// TB GB MB KB Byte bit
let path=require('path');
// extension name 扩展名 获取扩展名
console.log(path.extname('c:/a/b/c/index.html'));
dir目录的操作
文件目录(文件夹)操作
-
异步读取文件夹(读取目录)
fs.readdir('./', function (err, data) { if(!err) { // data 是一个数组 console.log(data); } });
-
同步读取文件夹
let dirRel = fs.readdirSync('./'); console.log(dirRel);
-
读取文件信息
fs.stat('./test.js', function (err, stats) { if(!err) { // stats 是一个文件信息对象 console.log(stats); } // 检测文件类型 console.log("是否为文件(isFile) ? " + stats.isFile()); console.log("是否为目录(isDirectory) ? " + stats.isDirectory()); }); Stats { dev: 16777220, mode: 16877, nlink: 9, uid: 501, gid: 20, rdev: 0, blksize: 4096, ino: 9264204, size: 306, 文件的大小 blocks: 0, atimeMs: 1583419107000, mtimeMs: 1583418753000, ctimeMs: 1583418753000, birthtimeMs: 1573702402000, atime: 2020-03-05T14:38:27.000Z, 最后一次访问的时间 mtime: 2020-03-05T14:32:33.000Z, 最后一次修改时间 ctime: 2020-03-05T14:32:33.000Z, 发生改变的时间 birthtime: 2019-11-14T03:33:22.000Z 创建的时间 }
-
创建文件夹、
fs.mkdir('./test', '0777', function (err) { if(!err) { console.log("创建文件夹成功"); } });
-
删除文件夹
fs.rmdir('./test', function (err) { if(!err) { console.log('文件夹删除成功'); } });
-
判断 文件夹/文件 是否存在
fs.exists('./test', function (bol) { console.log(bol); }); let isExit = fs.existsSync('./test');
-
通过相对路径获取绝对路径
fs.realpath('./upload.mp4', function (err, path) { // 如果路径没有错误,返回当前路径信息 if (!err) { console.log(path); } });
path路径模块
了解该模块
let path = require('path');
// 1.获取文件名
console.log(path.basename('http:www.baidu.com/one/two/thr.js'));
// 2.获取后缀名
console.log(path.extname('http:www.baidu.com/one/two/thr.js'));
// 3.获取目录,不包含文件名
console.log(path.dirname('http:www.baidu.com/one/two/thr.js'));
let strPath = './../a/../b/c/../d/e';
// 4.normalize: 规范化字符串路径
console.log(path.normalize(strPath));
// 5.获取当前目录(文件夹)的绝对路径
console.log(__dirname);
// 6.获取当前文件的绝对路径
console.log(__filename);
// 7.join: 合并, 并且整理路径
let joinStr = path.join('./x/../y/w', './a/b/c', './d/../m/n', './xx/../yy/ee');
console.log(joinStr);
// 8.resolve: 整理路径, 并返回目标文件的绝对路径
let p = path.resolve('www', 'f.txt', '../img/a/b/reba.jpg');
console.log(p);
:通过拼接路径,读取文件
let path = require('path');
let fs=require('fs');
let strpath=path.join(__dirname,'你好.txt');
fs.readFile(strpath,(error,data)=>{
if(error) return
console.log(data);
})
// 常用案例(使用public下的静态资源index.html)
fs.readFile(path.join(__dirname,'public','index.html'),'utf-8',(err,data)=>{
if(err){
return err;
}
console.log(data)
})
如果想要了解更多node中模块的底层原理,可以参考<深入浅出node.js>
链接:https://www.infoq.cn/article/nodejs-module-mechanism
案例:同步读取某个目录下所有文件
const getFiles = function(dir){
const results = [];
const files = fs.readdirSync(dir, 'utf8');
files.forEach(function(file){
const fullname = path.resolve(dir, file);
const stats = fs.statSync(fullname);
if(stats.isFile()){
results.push(fullname);
}else if(stats.isDirectory()){
results = results.concat( getFiles(fullname) );
}
});
return results;
};
const files = getFiles('/Users/kekobin/node-dir-test/');
安装nodemon
nodemon是一种工具,可以自动检测到目录中的文件更改时通过重新启动应用程序来调试基于node.js的应用程序。
安装
npm install -g nodemon
//或
npm install --save-dev nodemon
使用
nodemon ./main.js // 启动node服务
nodemon ./main.js localhost 6677 // 在本地6677端口启动node服务