模块是什么
在Node中模块是module,每个文件都被视为独立的模块,后来提出的CommonJS规范,使JS可以运行在任何地方、任何平台
CommonJS对模块的定义十分简单:
- 模块引用
- 模块定义
- 模块标识
模块化的好处:
- 为了降低程序之间的耦合性
- 提高程序代码的复用性
在node中,通过require()函数引入来自外部的模块,require的参数是一个文件的路径
模块化:
- 在Node中,一个js文件就是一个模块
- 在Node中,每一个js文件代码都是独立运行在一个函数中,而不是全局作用域,所以一个模块中的变量和函数在其他模块中无法访问
- 可以通过exports来向外暴露变量和方法,只需设置为exports的属性即可
模块分为两大类:
-
核心模块
- 由node引擎提供的模块 - 核心模块的标识,就是模块的名字
-
文件模块
- 由用户自己创建的模块 - 文件模块的标识就是文件的路径(绝对路径、相对路径)
在node中有一个全局变量global,它的作用和网页中的window类似,在全局中创建的变量都会作为global的属性保存
当node在执行模块中的代码时,它会把内容包装在一个函数里,如下:
打印这段话时console.log(arguments.callee + '')
会输出以下代码
function (exports, require, module, __filename, __dirname) {
// 模块中的内容
}
参数说明:
- exports 该对象用来将变量或函数暴露到外部,与module.exports指向同一个引用
- require 是一个函数,用来引入外部的模块
- module 代表是当前模块本身,exports就是module的属性,即可以用exports导出也可以用module.exports导出
__filename
当前模块的完成路径__dirname
当前模块所在文件夹的完成路径
注意: exports和module.exports的区别:
-
本质上指向的是同一个对象
-
通过exports只能使用
.
的方式来向外暴露内部变量exports.xxx = xxx
-
而module.exports即可以通过
.
的形式,也可以直接赋值module.exports.xxx = xxx module.exports = {}
-
如果exports通过赋值,则改变了对象引用,和module.exports不在是同一个对象指向
Buffer缓冲区
-
Buffer的结构和数组很像,操作的方法也和数组类似
-
数组中不能存储二进制文件,而Buffer就是专门用来存储二进制的数据
-
使用Buffer不需要引入模块,直接使用即可
-
Buffer中的存储的都是二进制数据,但是在显示时都是16进制格式
-
Buffer中每个元素的范围都是从00-ff(16进制) 0-255(10进制)
00000000
-11111111(2进制) -
计算机中的一个0或一个1称为1位(bit)
- 8bit = 1byte(字节) - 1024byte = 1KB - 1024KB = 1MB - 1024MB = 1GB - 1024GB = 1TB
-
Buffer中一个元素,占用内存的一个字节
文件系统fs模块
文件系统
- 就是通过node来操作系统的文件
- 使用文件系统,需要现引入fs模块,fs是核心模块,直接引入不需要下载
同步文件的写入
手动操作的步骤:
-
打开文件
fs.openSync(path, flagsp[, mode])
-
path 要打开文件的路径
-
flags 打开文件要做的操作类型
r 只读 w 可写
-
mode 设置文件的操作权限,一般不传
返回值:
- 该方法会返回一个文件的描述符作为结果,可以通过该描述符来对文件进行各种操作
-
-
向文件中写入内容
fs.writeSync(fd, string[, position[, encoding]])
- fd 文件的描述符,需要传递写入的文件的描述符
- string 要写入的内容
-
保存并关闭文件 fs.closeSync(fd)
- fd 文件的描述符
异步文件的写入
fs.open(path, flags[, mode], callback)
-
用来打开一个文件
-
异步调用的方法,结果都是通过回调函数返回的
-
回调函数两个参数
err 错误对象,如果没有错误则为null fd 文件的描述符
fs.write(fd, buffer[, offset[, length[, position]]], callback)
- 用来写入文件
fs.close(fd)
- 关闭文件
var fs = require("fs");
// 异步文件打开没有返回值-文件描述符
fs.open("hello2.txt", "w", function (err, fd) {
// 判断打开是否出错
if (!err) {
// 写入文件
console.log("打开文件成功");
fs.write(fd, "写入异步文件的内容", function (err) {
// 判断写入是否出错
if (!err) {
console.log("写入文件成功");
// 关闭文件
fs.close(fd, function (err) {
if (!err) console.log("关闭文件成功");
});
}
});
} else {
console.log(err);
}
});
简单文件的写入
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])
-
file 要操作的文件的路径
-
data 要写入的数据
-
options 选项,可以对写入进行一些设置
对象
{
- flags
r 只读
w 可写
a 追加
...
}
- callback 当写入完成以后执行的函数
// 引入模块
var fs = require("fs");
// 绝对路径C:\\Users\\admin\\Desktop\\test.txt
fs.writeFile("hello3.txt", "这是通过writeFile写入的内容", { flag: "a" }, function (err) {
if (!err) {
console.log("写入成功");
}
});
流式文件的写入
同步、异步、简单文件都不适合大文件的写入,性能较差,容易导致内存溢出
流式文件的写入
- 创建一个可写流
/**
* fs.createWriteStream(path[, options])
* - 用来创建一个可写流
* - path-文件路径
* - options 配置参数
*/
- 可以通过监听流的open和close事件来监听流的打开和关闭
/**
* on(事件字符串, 回调函数)
* - 可以为对象绑定一个事件
* once(事件字符串,回调函数)
* - 可以为对象绑定一个一次性的事件,该事件将会在触发一次以后自动失效
*/
var fs = require("fs");
var ws = fs.createWriteStream("hello4.txt");
// 通过ws向文件中输出内容
ws.write("通过可写流写入文件的内容");
ws.write("锄禾日当午");
ws.write("汗滴禾下土");
// ws.close();
ws.end();
// 监听事件
ws.once("open", function () {
console.log("流打开了~");
});
ws.once("close", function () {
console.log("流关闭了~");
});
文件的读取
-
同步文件的读取
-
异步文件的读取
-
简单文件的读取
fs.readFile(path[, options], callback)
fs.readFileSync(path[, options])
-
path 文件路径
-
options 读取的选项
-
callback 回调函数,通过回调函数将数据读取到内容,返回(err, data)
err 错误对象 data 读取到的数据,返回一个Buffer
-
-
流式文件的读取:流式文件读取也适用大文件,可以多次将文件读取到内存中
var fs = require("fs");
fs.readFile("测试1.jpg", function (err, data) {
if (!err) {
// console.log(data.toString()); // 如果是字符串
// console.log(data); // 如果是图片
// 写入到其他文件中
fs.writeFile("hello.png", data, function (err) {
console.log("图片复制成功");
});
}
});
var fs = require("fs");
// 创建一个可读流
var rs = fs.createReadStream("./hello2.txt");
// 创建一个可写流
var ws = fs.createWriteStream("copy1.txt");
// 监听可读流的开启和关闭
rs.once("open", function () {
console.log("可读流打开了~");
});
rs.once("close", function () {
console.log("可读流关闭了~");
// ws.close();
});
// 监听可写流的开启和关闭
ws.once("open", function () {
console.log("可写流打开了~");
});
ws.once("close", function () {
console.log("可写流关闭了~");
});
// 如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,data事件绑定完毕,它会自动开始读取数据
/* rs.on("data", function (data) {
// console.log(data.length);
// 将读取到的数据写入到可写流中
ws.write(data);
}); */
// pipe()可以将可读流中的内容直接输出到可写流中
rs.pipe(ws);
fs中其它方法
1、fs.existsSync(path) 检查文件是否存在
/**
* fs.existsSync(path) 检查文件是否存在
*/
var fs = require("fs");
var isExist = fs.existsSync("111.js");
console.log(isExist);
2、fs.stat(path, callback)与fs.statSync(path)
- 获取文件的状态
- 返回一个对象,对象中保存了当前状态的相关信息
fs.stat("./01_buffer.js", function (err, stat) {
if (!err) {
console.log(stat.isFile()); // 是否是一个文件
console.log(stat.isDirectory()); // 是否是一个文件夹(目录)
}
});
3、fs.unlink(path, callback)与fs.unlinkSync(path)
- 删除文件
fs.unlinkSync("hello.txt");
4、fs.readdir(path[, options], callback)与fs.readdirSync(path[, options])
-
读取一个目录的结构
回调函数中的files是一个字符串数组,每个元素就是一个文件夹或文件的名字
fs.readdir(".", function (err, files) {
if (!err) {
console.log(files);
}
});
5、 fs.ftruncate(fd[, len], callback)与fs.ftruncateSync(fd[, len])
- 截断文件,将文件修改为指定的大小,中文大小为3个字节,多余的会乱码
fs.truncateSync("hello2.txt", 10)
6、fs.mkdir(path[, mode], callback)与fs.mkdirSync(path[, mode])
- 创建一个目录
7、 fs.rmdir(path, callback)与fs.rmdirSync(path)
- 删除一个目录
fs.mkdirSync("hello");
fs.rmdirSync("hello");
8、fs.rename(oldPath, newPath, callback)与fs.renameSync(oldPath, newPath)
-
对文件进行重命名
-
参数
oldPath 旧的路径 newPath 新的路径 callback 回调函数
fs.renameSync("copy.txt", "命名.txt");
9、fs.watchFile(filename[, options], listener)
-
监听文件的修改
-
参数:
filename 要监听的文件路径 options 配置选项 listerner 回调函数,当文件发生变化时,回调函数会执行,在回调函数中会有两个参数: current 当前文件的状态 previous 修改前文件的状态 这两个对象都是Stats对象
var fs = require('fs');
fs.watchFile("hello2.txt", { interval: 1000 }, function (current, previous) {
console.log("修改前文件大小:" + previous.size);
console.log("修改后文件大小:" + current.size);
});