一、node操作 非阻塞说明
引入一个文件系统模块
let fs=require(‘fs’);
引入别的js文件,返回的是一个对象
let p=require(’./second.js’);
js文件中的变量等,通过暴露,被引入,在新文件中都变成该对象(p)的属性或者方法
1.readFile–读取文件
fs.readFile(‘目标文件路径’,‘字符集’,(‘错误’,‘读取到的数据’)=>{回调函数});
二、事件驱动
node核心API构建用的是异步事件驱动框架 events模块,提供events.EventEmitter对象
事件绑定使用on方法 事件触发使用emit方法
// 引入核心模块 events
const events = require('events');
// 实例化仅有的一个实例 得到一个对象
const event = new events.EventEmitter();
// 使用该对象进行绑定事件
// 绑定事件使用on方法 内置两个参数
// 第一个参数是事件的名字
// 第二个参数是回调函数 回调函数其实就是事件的行为
// 可以给回调函数传递参数 若干参数 因为这是一个自定义的函数
event.on('I_LOVE_YOU',(aname,bname)=>{
console.log('终于等到你');
});
// 触发事件的时候 使用emit方法
// 内置参数若干 第一个参数是我们触发的事件名
// 从第二个参数开始 都是事件的参数 如果没有参数 那么emit方法内置一个参数 参数是事件的名字
event.emit('I_LOVE_YOU','Eric','Marry');
event.emit('I_LOVE_YOU','Eric','Marry');
event.emit('I_LOVE_YOU','Eric','Marry');
event.emit('I_LOVE_YOU','Eric','Marry');
三、模块
1.概念
模块就是一个JS文件 将我们已有的程序进行一个不封装 当我们需要再次使用的时候 直接引入
2.核心模块
核心模块是安装Node时,自带的模块;不需要下载,定义,我们可以直接使用。
使用require函数进行引入模块,引入进来的是一个对象、
常用的核心模块 fs events url path http querystring
核心模块少,完成基本功能,大多是使用JS的逻辑和代码,使用到更复杂的逻辑 那么需要依赖第三方模块
3.第三方模块
第三方模块的使用依赖于npm命令 我们使用npm进行模块的下载
npm是包管理工具,主要用来做模块的发布 依赖 下载 安装等工作
NPM命令
init : 初始化命令 下载包之前必须初始化 生成package.json
install/i : 下载包 安装包 生成node_module文件夹 装包的 生成package_look.json 包的信息
install/i@x.x : 下载包 安装包 指定版本号
search/s : 查看包
install/i -g : 全局安装 只有工具类的模块才会使用全局安装 全局安装之后会带给我们一个命令
install/i --save || install -S : 安装运行依赖
install/i --save-dev || install -D : 安装开发依赖
remove/r : 删除包
uninstall : 卸载包
4.自定义模块
自定义模块就是我们自己定义的JS文件 将其封装 然后暴露;可以自行引入,使用
暴露 : exports || module.exports
引入 : require 在NodeJS中引入模块 一直使用require
引入自定义模块的时候注意要写路径 即使是当前目录 也不能省略./
// 第一种暴露方式
// 使用export方式进行暴露 这种方式不常用
/*
exports.username = 'admin';
exports.password = '123';
exports.fun = ()=>{
console.log('fun函数');
}
exports.obj = {
// username,password 因为username password不是变量 所以说不能这样暴露
name : 'Eric',
age : 18
};
*/
// 第二种暴露方式
// 使用modult.exports
// module.exports.username = 'admin';
// module.exports.password = '123';
// module.exports.fun = ()=>{
// console.log('fun函数');
// }
// module.exports.obj = {
// // username,password 因为username password不是变量 所以说不能这样暴露
// name : 'Eric',
// age : 18
// };
// 堆栈空间都保持一致
// console.log(exports);
// console.log(module.exports);
// console.log(module.exports === exports);
// let obj1 = {a:1};
// let obj2 = {a:1};
// console.log(obj1 == obj2);
module.exports.username = 'admin';
exports.password = '123';
exports.fun = ()=>{
console.log('fun函数');
}
exports.obj = {
// username,password 因为username password不是变量 所以说不能这样暴露
name : 'Eric',
age : 18
};
// 第三中暴露方式 最常用的方式
let name = 'Eric';
let age = 18;
let username = 'admin';
let password = '123';
let func = ()=>{
console.log('这是哈数');
}
let obj = {
name,age,username,password
}
module.exports = {
obj,func
}
// 如果说同时使用export和module.exports两种方法暴露
// 那么module.exports会覆盖exports
node顶级对象
// __dirname : 获取当前文件夹的绝对路径
console.log(__dirname);
// __filename : 获取当前文件的绝对路径
console.log(__filename);
四、buffer
1.概念
Buffer 结构和数组非常像 操作的方法也相似 数组中不能存储二进制的文件 而buffer专门存储二进制的数据
文件流的写入 网络请求数据处理 javascript 语言不能读取或操作数据流机制
buffer在全局作用域 不需要引入 直接使用 buffer中存储的是二进制的数据 显示的时候 是以16进制显示
buffer中每个元素从00-ff 0-255 buffer 中的每个元素 占用内存的一个字节 8比特
一个汉字占有三个字节 buffer大小一旦确定 不能修改 buffer是对底层内存的直接操作
2.方法
buffer.length属性 : 查看Buffer的长度
Buffer.from(str) : 将一个字符串转换成buffer
buf.toString(); : 将缓冲区的数据 转成字符串
let str='1234';
//字符串转buffer
console.log(Buffer.from(str));
//buffer转字符串
let buff=Buffer.from(str);
console.log(buff.toString());
//buffer转base64
console.log(buff.toString('base64'));
//base64转buffer
let base64=buff.toString('base64');
console.log(Buffer.from(base64,'base64'));
五、文件操作
NodeJS是可以对文件进行操作的 能操作所有类型的文件 对文件的操作主要包括 文件的读取 文件的写入
在文件操作中 使用的模块是我们的核心模块 fs模块 fileSystem
文件的读取和文件的写入,每一个方法其实都是两个 有一个同步方法 还有一个异步方法
同步方法方法的名字在后面加上Sync,同步的方法比异步的方法多了一个返回值 异步方法比同步方法多了一个回调函数
1.文件读取
1.异步–readFile
内置两个或者三个参数 第一个参数是文件的路径 第二个参数是可选–字符集(传递则按charset读取,不传按buffer读取)
第三个参数是回调函数,回调内置两个参数 第一个参数是错误 第二个参数是读取的数据
2.同步–readFileSync
内置一个或者两个参数 第一个参数是文件路径 第二个参数是可选–字符集
const fs=require('fs');
//异步读取
fs.readFile('./01.firstnode.js','utf-8',(error,data)=>{
if(error) console.log(读取失败);
else console.log(data);
})
//同步读取
let data=fs.readFileSync('./01.firstnode.js','utf-8');
console.log(data);
2.文件写入
数据写入到文件,如果写入的文件不存在 那么会自动创建文件;我们文件写入分为三步组成
1.同步写入 最醒目,最清晰
- 打开文件 openSync(文件路径,打开方式,打开权限:‘一般不传’) 返回值是资源句柄
打开方式:r–只读打开,w–写入打开 覆盖写,a–写入打开 追加写 - 写入数据 writeSync(资源句柄,写入的数据,字符集,写入起始位置:‘一般不传’)
- 关闭文件 closeSync(资源句柄)
let fs=require('fs');
//同步写入
//1.打开文件 openSync (文件路径,打开方式,打开权限:'一般不传') 返回值是资源句柄
let op=fs.openSync('./test.txt','a');
console.log(op);
//2.写入数据 writeSync (资源句柄,写入的数据,字符集,写入起始位置:'一般不传')
let str='憨憨';
fs.writeSync(op,str,'utf-8');
//3.关闭文件 closeSync (资源句柄)
fs.closeSync(op);
2.异步写入
与同步写入相似,方法名去掉Sync,返回值在回调函数中作为参数
4. 打开文件 open(文件路径,打开方式,打开权限:‘一般不传’,(错误,资源句柄)=>{ })
打开方式:r–只读打开,w–写入打开 覆盖写,a–写入打开 追加写
5. 写入数据 write(资源句柄,写入的数据,字符集,写入起始位置:‘一般不传’,(错误)=>{ })
6. 关闭文件 close(资源句柄,(错误)=>{ })
//异步写入
let fs=require('fs');
let str1='但是';
fs.open('./test.txt','a',(error,data)=>{
if(error) console.log('打开失败');
else {
fs.write(data,str1,'utf-8',(error)=>{
if(error) console.log('写入失败');
else console.log('写入成功');
})
fs.close(data,(error)=>{
if(error) console.log('关闭失败');
else console.log('关闭成功');
})
}
})
3.简单写入
简单写入操作 我们使用的最多 简单,只涉及到一个方法 打开和关闭都不需要
writeFile(文件路径,写入内容,{对象属性’flag 写入方式’;字符集’encoding’},(error)=>{ }) : 写入文件操作
//简单写入
let fs=require('fs');
let str2='我喜欢';
fs.writeFile('./test.txt',str2,{flag:'a',encoding:'utf-8'},error=>{
if(error) console.log('写入失败');
else console.log('写入成功');
})
4.流式文件写入
流式文件操作需要使用事件驱动,使用的时候比较少
流式操作有一个优势,他可以进行大批量的数据写入,所以使用流式操作 一般情况下的写入方式都是追加写
- 创建可写的流createWriteStream(文件路径,{flag,encoding}) 返回值是资源 使用资源进行触发事件
触发后使用资源中write方法进行写入,写入后使用资源中end方法进行结束
//流式写入
const fs=require('fs');
let data=fs.createWriteStream('./test.txt',{flag:'w',encoding:'utf-8'});
data.on('open',()=>{
console.log('打开流');
})
data.write(`开心点/n`);
data.on('close',()=>{
console.log('关闭流');
})
data.end();