Node.js学习(二)----- 常用模块
1、fs(文件系统)
- Buffer(缓存区)----- 在全局作用域中,无需require
- 为什么用Buffer?
在Node、ES6出现之前,前端工程师只需要进行一些简单的字符串或DOM操作就可以满足业务需要,所以对二进制数据是比较陌生。但node出现以后,前端工程师面对的技术场景发
生了变化,可以深入到网络传输、文件操作、图片处理等领域,而这些操作都与二进制数据紧密相关。Node里面的buffer,是一个二进制数据容器,数据结构类似与数组,专门用于
Node中数据的存放。 - Buffer的基本使用
- 历史使用 :
const buf1 = new Buffer(10); 安全隐患: 分配到的内存可能还存储着旧数据,这样就存在安全隐患
- 新使用方式:
- Buffer.from(str) ----- 将一个字符串转换为buffer存储
var str = 'i will to change buffer!' const buf = Buffer.from(str) console.log(str.length) console.log(buf) console.log(buf.length) console.log(buf.toString())
运行结果:Buffer中存储的都是二进制数据,但是在显示时都是以16进制的形式显示
- Buffer.from(str) ----- 将一个字符串转换为buffer存储
- 历史使用 :
- 为什么用Buffer?
-
-
-
- Buffer.alloc(size) ----- 创建一个指定大小的Buffer( 注意:buffer的大小在初始化时就确定,不能动态改变 )
var buf = Buffer.alloc(5) console.log(buf) buf[0] = 10; buf[1] = 255; buf[2] = 0xaf; buf[5] = 12;//超出的时候不进行处理 console.log(buf) console.log(buf[2])// 输出都是以10进制输出 console.log(buf[2].toString(16)) buf.forEach((item, index)=>{ console.log(index + ":" + item); });
运行结果:
- Buffer.alloc(size) ----- 创建一个指定大小的Buffer( 注意:buffer的大小在初始化时就确定,不能动态改变 )
-
-
-
-
- Buffer.allocUnsafe(size) ----- 创建一个指定大小的Buffer,但是可能包含敏感数据
var buf = Buffer.allocUnsafe(5) console.log(buf)
运行结果:
-
Buffer.allocUnsafeSlow()
- Buffer.allocUnsafe(size) ----- 创建一个指定大小的Buffer,但是可能包含敏感数据
- Buffer使用相关注意点
- Buffer的结构和数组很像,操作的方法也和数组类似;
- Buffer中是以二进制的方式存储数据的;
- Buffer是Node自带,不需要引入,直接使用即可
-
- fs基本概念:
- 在Node中,与文件系统的交互是非常重要的,服务器的本质就将本地的文件发送给远程的客户端;
- Node通过fs模块来和文件系统进行交互,该模块提供了一些标准文件访问API来打开、读取、写入文件,以及与其交互;
- 要使用fs模块,首先要从核心模块中加载:const fs = require("fs");
- fs使用特点:
- fs模块中所有的操作都有两种形式可供选择同步和异步;
- 同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码;
- 异步文件系统不会阻塞程序的执行,而是在操作完成时,通过回调函数将结果返回;
- 文件操作的基本使用方式:
- 创建目录(文件夹):fs.mkdir("目录名称",cb)
const fs = require("fs"); fs.mkdir("test", function (err) {//test是目录的名称 if (err) { console.log("fail")//目录已经存在 } else { console.log("success") } })
- 删除目录(文件夹):fs.rmdir("目录名称",cb)
- 注意:rmdir()只能删除空目录
fs.rmdir("./test", function (err) { if (err) { console.log(err) console.log("文件夹删除失败") } else { console.log("文件夹删除成功") } })
- 当目录下存在文件时,删除失败
- 注意:rmdir()只能删除空目录
- 创建目录(文件夹):fs.mkdir("目录名称",cb)
-
- 删除文件:fs.unlink("目录名称",cb)
fs.unlink("./test/test.txt", function (err) { if (err) { console.log(err) console.log("文件删除失败") } else { console.log("文件删除成功") } })
- 列出目录下的所有文件:fs.readdir("目录名称",cb)
fs.readdir("../basic", function (err, files) { if (!err) { console.log(files) } })
- 删除文件:fs.unlink("目录名称",cb)
-
- 对目录和文件进行重命名: fs.rename(oldFile,newFile,cb)
- 基本使用:
fs.rename("test", "suffer", function (err) { if (!err) { console.log("文件重命名成功") } })
- 隐藏功能:移动文件
fs.rename("./test", "../suffer", function (err) { if (!err) { console.log("文件重命名,并且移动成功") }else{ console.log(err) } })
- 基本使用:
- 要检查文件是否存在,并且随后对其进行操作:fs.stat("路径",cb)
var arr = ["../basic", "./app.js"] for (let data of arr) { fs.stat(data, function (err, files) { if (err) { console.log(err) } else if (files.isFile()) { console.log("----------") console.log(`${data}是文件`) } else { console.log(files.isDirectory()) console.log(`${data}是目录`) } }) }
- 写入文件操作:
- 简单文件写入:
// 简单文件写入 // fs.writeFile(file, data[, options], cb) // fs.writeFileSync(file, data[, options]) // file 要写入文件的路径 // data 要写入的数据 // options 选项,可以对写入进行一些设置 r 只读 w 可写 a 追加 默认值为w,文件不存在则创建文件 // cb 回调函数 当写入完成以后执行的函数 const fs = require("fs"); var data = 'my name is ABU!'; fs.writeFile("write.txt",data,{flag:"w+"},(err)=>{ if(!err){ console.log("write successly!") }else{ console.log(err) } })
- 异步方法:
var originalData = 'my name is sicly!' var newData = 'my name is jack later!' fs.writeFile("write.txt", originalData, function (err) { if (err) { console.log(err) } else { console.log("write successly!") } })
运行结果:
- 异步方法:
- 简单文件写入:
- 对目录和文件进行重命名: fs.rename(oldFile,newFile,cb)
当写入newData时,运行结果是:
与方法appendFile的对比:当运行完上述两段代码时,结果为:
总结:writeFile与appendFile执行时,当文件名不存在的时候,都能够自动创建文件,但是前者是重复写重复替换文件内容,而后者是一直追加文件内容;
-
-
-
- 同步方法:
fs.writeFileSync("write.txt", newData)
- 同步方法:
- 同步文件写入:
// 同步文件的写入 // 手动操作的步骤 // 1、打开文件 // fs.openSync(path, flags[, mode]) // path 要打开文件的路径 // flags 打开文件要做的操作的类型 r 只读的 w 可写的 // mode 设置文件的操作权限,一般不传 //返回值:该方法会返回一个文件的描述符作为结果,我们可以通过该描述符来对文件进行各种操作 // 2、向文件写入内容 // fs.writeSync(fd, string[, position[, encoding]]) // fd 文件的描述符,需要传递要写入的文件的描述符 // string 要写入的内容 // position 写入的起始位置 // encoding 写入的编码,默认为utf-8 // 3、保存并关闭文件 // fs.closeSync(fd) // fd 要关闭的文件的描述符 const fs = require("fs"); var fd = fs.openSync("write.txt","w"); var data = 'my name is lily!' fs.writeSync(fd,data,2); console.log("write succelly!") fs.closeSync(fd) console.log("file has closed") console.log("同步方法写入文件内容后,继续往后运行~")
- 异步文件写入:
// 异步文件的写入 // fs.open(path, flags[, mode], cb) // 用来打开一个文件 // 异步调用的方法,结果都是通过回调函数的参数返回的,有两个参数 // err 错误对象,如果没有错误则为null // fd 文件的描述符 // fs.write(fd, string[, position[, encoding]], cb) // 用来异步写入一个文件 // fs.close(fd, cb) // 用来关闭文件 const fs = require("fs"); fs.open("write.txt","w",(err,fd)=>{ if(err){ console.log(err) }else{ fs.write(fd,'i have a cute rabbit!',2,'utf-8',(err)=>{ if(!err){ console.log("write succelly!") } fs.close(fd,(err)=>{ if(!err){ console.log("file has closed") } }) }) } }) console.log("异步任务执行!")
运行结果:非阻塞
-
-
-
-
- 流式文件写入:
// 流式文件写入 // 如同流水般,可以持续的写入内容到文件 // 管道:适合大批量数据写入 // 1、引入模块 const fs = require("fs"); // 2、创建写入流 let ws = fs.createWriteStream("write.txt"); // 3、打开管道 // 通过监听流的open与close事件来判断流的打开与关闭 // 一次性事件 once ws.once("open",(err)=>{ console.log("stream open!") }) ws.once("close",()=>{ console.log("stream closed!") }) // 4、写入内容 ws.write("我在马路边,") ws.write("捡到一分钱") // 5、关闭通道 ws.end()
运行结果:
- 流式文件写入:
-
-
- 读取文件操作:
- 简单文件读取:
// 简单文件读取 // fs.readFile(path[, options], cb) // cb有两个参数 err 代表错误参数 data既可以是String和Buffer // fs.readFileSync(path[, options]) const fs = require("fs"); fs.readFile("write.txt",'utf-8',(err,data)=>{ if(!err){ console.log(data)//不加utf-8则返回Buffer console.log(data.toString()) }else{ console.log(err) } }) const fs = require("fs"); var data = fs.readFileSync("write.txt",'utf-8') console.log(data)
- 流式文件读取:
- 注意:如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,data事件绑定完毕,它会自动开始读取数据;
-
const fs = require("fs"); var rs = fs.createReadStream("write.txt") var content = "" rs.on("data",(data)=>{ content += data.toString() }) rs.on("end",()=>{ console.log(content) })
- pipe ----- 就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来。读取的所有流数据就自动写入到目标文件中;
var fs = require('fs'); var rs = fs.createReadStream('sample.txt'); var ws = fs.createWriteStream('copied.txt'); rs.pipe(ws);
- 简单文件读取:
- 读取文件操作:
2、http
- http服务器
const http = require('http'); /** * Create HTTP server */ const server = http.createServer(function (request, response) { // 获得HTTP请求的method和url: console.log(request.method + ': ' + request.url); // 将HTTP响应200写入response, 同时设置Content-Type: text/html: response.writeHead(200, { 'Content-Type': 'text/html' }); // 将HTTP响应的HTML内容写入response: response.end('<h1>Hello world!</h1>'); }) server.listen('8080', (error) => { if (error) { console.log(error) } else { console.log(`Server is running at http://127.0.0.1:8080/`) } })
3、events(事件触发器)
- 基本使用:
- 引入模块:
var events = require('events');
- 绑定一个事件:
var myEmitter = new events.EventEmitter();
- 监听事件:
myEmitter.on("someEvent", function (data) { console.log(data) })
- 触发事件:
myEmitter.emit("someEvent", 'the event was emitted')
- 引入模块:
- 使用util
4、process(代表当前Node.js进程)
- process.cwd() 可以返回当前的工作目录
- 同时process可以监听到进程的退出
process.on('exit', function (code) { console.log('about to exit with code: ' + code); });
-
我们可以根据不同环境提供的全局对象(浏览器是window,node是global),判断当前JavaScript代码的运行环境
const isNode = () => typeof window === 'undefined'
5、遇到的问题
暂无