笔记来自于视频:尚硅谷-快速入门nodejs
简介
概述
之前的JavaScript代码是在浏览器客户端执行的,而Node.js可以使JavaScript代码在服务器上运行。Node的用途:
- Web服务API,比如REST·实时多人游戏
- 后端的Web服务,例如跨域、服务器端的请求
- 基于Web的应用
- 多客户端的通信,如即时通信
Node.js的安装
在Windows系统上安装Node.js请参考:安装Node.js
在Linux系统上安装Node.js请参考:在Linux上安装Node.js
Node.js执行js文件
Node.js执行js文件,即"node js文件名.js"。
webstorm集成node.js
创建的时候指定node.js
或者在Setting中配置Node.js
模块化
模块化概念
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。
模块化的好处
- 降低耦合性
- 代码复用
引入模块
在Node.js中一个js文件就是一个模块。在Node.js中,通过require()
函数来引入外部模块,该函数可以传入一个文件的路径作为参数,会自动根据该路径引入外部模块,如果是相对路径必须是.
或..
开头,不能省略。
var mo = require("./world.js");// 返回一个对象,就是导入的模块
在Node.js中,每个js文件中的js代码都是独立运行在一个函数中的,而不是全局作用域,所以在一个模块中的变量和函数在其他模块中无法访问。注意:核心模块和第三方模块都可以直接在require()
方法中写模块名就可以引入,如果是自己定义的模块则需要根据路径进行引入。
可以从上面的代码中看出即使引入了其他模块,也无法调用其他模块中的属性和方法。因此需要通过exports
来向外部暴露变量和函数,只需要将需要暴露的变量或函数设置为exports
的属性即可。语法如下:
exports.变量名 = 变量值;
exports.函数名 = function ([参数列表]) {
函数体
};
示例如下:
练习:
math.js
exports.add = function (a, b) {
return a + b;
};
exports.sub = function (a, b) {
return a / b;
};
test.js
// 引入math.js模块,模块名命名为math
var math = require("./math.js");
// 调用math模块中的方法
var addResult = math.add(1, 2);
console.log(addResult);
var subResult = math.sub(4, 2);
console.log(subResult);
使用模块
模块的引用:
// 引入js文件
var 模块名 = require(模块路径);
// 引用模块
模块名.变量名;
模块名.函数名([参数列表]);
我们使用require()
引入外部模块时,使用的就是模块标识,可以通过模块标识来找到指定的模块。模块分为两大类:
- 核心模块(由Node引擎提供的模块,核心模块的标识就是模块名,既可以直接通过模块名进行引入,例如:
var mo=require("fs")
。) - 文件模块(即由用户自己创建的模块,文件模块的标识就是文件的相对路径或绝对文件,相对路径必须使用
.
或..
开头。)
实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了5个实参,所以在模块中可以直接使用这五个实参。
function (exports, require, module, __filename, __dirname) {
}
在Node中有一个全局对象global
,它的作用和网页中的window
类似,在全局中创建的变量都会作为global
的属性保存,在全局中创建的函数都会作为global
的方法保存。其实Node在执行模块中的代码时首先会在代码的最顶部添加function (exports, require, module, __filename, __dirname) {
,然后在代码的最底部添加}
。所以模块中的代码是无法被外界访问到的,我们可以通过arguments.callee
来查看当前执行的函数对象,证明了模块中的代码实际上是包装在一个函数中的,所以模块中的变量也是局部变量。
其实上面的五个参数也是每个模块中的内置对象,可以直接调用,关于它们的说明如下:
exports
:该对象用来将变量或函数暴露到外部。require
:是函数,用来引入外部的模块。module
:对象,module
代表的是当前模块本身,而exports
就是module
的属性,所以既可以使用exports
导出,又可以使用module.exports
导出,更推荐后者。__filename
:属性,表示当前模块的完整路径,如C:\Users\abc\projects\test01.js
__dirname
:属性,表示当前模块所在文件夹的完整路径,如C:\Users\abc\projects
module.exports
可以有两种暴露方式,语法如下:
// 第一种暴露方式
module.exports.变量名 = 变量值;
module.exports.函数名 = function ([参数列表]) {
函数体
}
// 第二种暴露方式,可以直接暴露多个变量和函数,而exports={}则不行
module.exports = {
变量名: 变量值,
函数名: function ([参数列表]) {
函数体
};
例如:
world.js
// 第一种暴露方式
// module.exports.msg = "hello world";
// module.exports.hello = function (msg) {
// console.log(msg);
// };
// 第二种暴露方式
module.exports = {
name: '张三',
age: 18,
print: function (msg) {
console.log("打印:" + msg);
}
};
hello.js
var mo = require('./world.js');
// console.log(mo.msg);
// mo.hello("你好");
console.log(mo.name);
console.log(mo.age);
mo.print("hello node.js");
注意:两种方式不能同时使用,否则会报错。关于exports
和module.exports
的区别参考:module.exports与exports,export与export default之间的关系和区别
包
概述
总结:包是模块的集合。
但包不仅仅是js模块文件,而是包含着其他文件,遵循着一定的规范。规范要求包由包结构和包描述文件两个部分组成:
- 包结构:用于组织包中的各种文件
- 包描述文件:即package.json文件,描述了包的相关信息如包名、版本、依赖等,以供外部读取分析。
包结构
包实际上是一个压缩文件,解压后还原为目录。符合包规范的目录,应该包含如下文件和文件夹:
- package.json:包的描述文件,描述了包的相关信息如包名、版本、依赖等,是必须要有的文件。
- bin:文件夹,包含了可执行的二进制文件,非必须。
- lib:文件夹,包含了js代码,非必须。
- doc:文件夹,包含了文档文件,非必须。
- test:文件夹,包含了单元测试文件,非必须。
包描述文件
包描述文件package.json就是用来描述包相关信息的一个json文件,位于包的根目录向下,是包必不可少的组成部分。但注意json文件中不可写注释。而package.json文件中的重要字段说明如下:
- name:必须要有的属性,模块名称。注意不能包含大写字母。
- version:必须要有的属性,与name属性组成了一个npm模块的唯一标识符。
- description:包描述信息,告诉别人这个包有什么作用,能提供什么功能。
- keywords:一个字符串数组,便于别人搜索到该包。
- license:规定的协议,例如MIT。
- author:该包的作者名。
- contributors:该包的一些其他贡献者姓名。
- main:指定了程序的主入口文件。
更多详细信息可以参考:npm package.json属性详解
npm
概述
总结:npm就是管理包的,类比Java中的maven。
NPM是Node Package Manager的缩写,即Node包的管理工具。对于Node而言,NPM帮助其完成了第三方模块的发布(可以将自己写的包发布到npm上)、安装(也可以通过npm来安装第三方包)和依赖(有些包会依赖其他包,而通过npm会自动下载相关的依赖包,而不需要手动去一个个寻找依赖包)等。借助NPM,Node与第三方模块之间形成了很好的一个生态系统。
在安装成功Node.js之后,npm就一起安装了,所以可以直接使用,打开DOS窗口,输入npm
出现如下帮助内容就表示npm工具是可用的。
npm可以通过一些简单的命令来安装、卸载、管理包,在命令行窗口使用。常用的命令如下:
npm -v
:查看npm工具的版本。npm version
:查看所有包的版本。npm search 包名
:根据包名搜索包,例如:npm search math
。npm install 包名
:安装指定包,注意在哪个目录执行安装命令就安装在哪个目录下,而且可以通过npm i 包名
简化安装命令来安装。执行安装命令后会生成一个node_modules文件夹和package-lock.json文件,而在node_modules文件夹下才是安装的模块。如npm install math
。npm remove 包名
:删除指定包。在任何目录下执行删除命令都可以删除,而不必要到该包的安装目录下执行。还可以通过npm r 包名
简化删除命令。如npm remove math
。npm install 包名 --save
:在安装包的时候一起添加到package.json文件中的dependencies属性中,表示依赖的包。npm install
:下载当前项目所依赖的包。如当我们从网络上下载一个项目,而该项目所需要的依赖是放在node_modules目录下的,但该目录并不会被上传,因为文件很大很多,会导致上传下载速度变慢,所以关于项目所依赖的包信息是放在package.json文件中的dependencies属性中,而执行npm install
命令就可以把这些包统一下载下来。所以以后在下载一个项目后,先执行该命令下载依赖的包。npm install 包名 -g
:全局安装包,一般用于一些工具,很多项目都会用到,而不是只有一个项目用到。npm init
:使用命令行快速创建package.json文件。而npm init -y
可以直接默认创建所有选项。npm list
:显示该项目下的包列表。
webstorm使用npm
可以在Terminal
面板执行npm命令安装、删除、管理包:
还可以在
Settings
——>Languages & Frameworks
——>Node.js and NPM
中管理包,但是全局安装的。
当我们想把自己的项目上传到npm时不需要把依赖(即node_modules文件夹)也上传,上传下载速度会变慢,也不能保证是最新的,有了dependencies后就可以根据这配置信息自动下载依赖包。所以在网上下载第三方包后,先执行
npm install
命令下载当前项目所依赖的包。
配置镜像
npm的服务器在国外,下载很慢,所以可以考虑使用国内有镜像服务器。有两种方式:
- 第一种方式:使用命令配置。
# 第一步,设置国内镜像网站
npm config set registry https://registry.npm.taobao.org
# 第二步,验证是否设置国内镜像成功,打印结果是上面的网站则表示配置镜像成功
npm config get registry
- 第二种方式:使用cnpm安装
# 第一步,安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 第二步,使用cnpm进行安装等操作
cnpm install 包名
注意:通过npm下载的包都放在node_modules文件夹中,我们通过npm下载的包,可以直接通过包名引入,如var 名字 = require(包名)
。Node.js在使用模块名引入模块时,首先会在当前目录的node_modules中寻找是否含有该模块,如果有则直接使用,如果没有则去上一级目录的node_modules中寻找,如果有则直接使用,如果没有则再去上一级目录中寻找,直到找到为止,直到找到磁盘的根目录,如果依然没有则报错。
文件系统fs
Buffer
Buffer的引入:由于数组中不能存储二进制的文件,所以需要使用Buffer来专门存储二进制数据。
使用Buffer不需要引入模块,直接使用即可。在Buffer中存储的都是二进制数据,但是打印显示时都是以16进制的形式显示。
- 将字符串写入到Buffer
// 准备一个待放入到Buffer的字符串
var str = "hello world";
// 调用Buffer.from()将字符串放入到buffer中
var buf = Buffer.from(str);
console.log(buf);// <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
- 创建指定大小的Buffer
// 使用Buffer.alloc(size)创建一个指定大小的buffer,size表示字节数
var buffer = Buffer.alloc(10);
// 然后可以使用类似于数组下标的方式赋值
buffer[0] = 1;
buffer[1] = 200;
buffer[2] = 123;
buffer[11] = 55;// 即使超过索引范围,也不会报错,但也不会赋值成功
console.log(buffer);
// 同样可以下标索引的方式访问buffer中的元素
console.log(buffer[1]);
// 也可以通过for循环的方式遍历
for (var i=0; i < buffer.length; i++) {
console.log(buffer[i]);
}
注意:buffer中的一个元素,占用内存的一个字节。Buffer的大小一旦确定,则不能修改,Buffer实际上是对底层内存的直接操作。
- 将buffer中的数据转换成字符串
var str = "我是一段文本数据:hello world.";
var buffer = Buffer.from(str);
// 通过buffer.toString()方法可以直接访问缓冲区的内容
console.log(buffer.toString());
Buffer相关方法:
Buffer.from(str)
:将一个字符串转换成bufferBuffer.alloc(size)
:创建一个指定大小的buffer,size指的是字节数Buffer.alloUnsafe(size)
:创建一个指定大小的buffer,但可能包含敏感数据buffer.toString()
:将buffer中的数据转换为字符串,其中buffer是创建好的缓冲区对象
模块fs概述
fs是Node提供的一个模块,该模块提供了一些API用来操作本地的文件,如打开、读取、写入文件等操作。类似于Java操作本地文件。fs是核心模块,要使用则需要对其进行加载:
var fs = require("fs");
fs模块中所有操作都有两种形式可选择:同步和异步。同步指操作代码会逐步执行,比如说读文件,要将文件所有内容都读取到内存中才会执行下面的代码。异步不会阻塞程序的执行,是在操作完成时通过回调函数将结果返回,比如说读文件,会继续执行下面的代码,而文件的所有内容会通过回调函数返回,不会影响到下面代码的执行。
文件的写入
同步文件写入
sync表示同步。
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,打开文件
var fd = fs.openSync(path, flags[, mode]);
参数:
- path:待打开文件的路径,如:C:\\Users\\Administrator\\hello.txxt
- flags:打开文件要做的操作的类型。r表示只读;w表示只写。
- mode:可选参数,设置文件的操作权限,一般不传。
返回值:
- 该方法会返回一个文件描述符作为结果,我们可以通过该描述对文件进行各种操作
第二步,向文件中写入内容
fs.writeSync(fd, string[, position[, encoding]]);
参数:
- fd:文件的描述符,通常传入openSync()方法的返回值
- string:待写入的内容
- position:可选参数,表示在文件中写入的起始位置
- encoding:可选参数,写入编码,默认为utf-8
第三步,保存并关闭文件对象
fs.closeSync(fd)
参数:
- fd:待关闭文件的描述符
例如:
// 导入fs模块
var fs = require("fs");
// 第一步,打开文件,如果文件不存在则会创建
var fd = fs.openSync("hello.txt", "w");
// 第二步,向文件中写入内容
fs.writeSync(fd, "hello world. 这是向文件中写入的内容。");
// 第三步,关闭文件
fs.closeSync(fd);
异步文件写入
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,打开文件,异步调用的方法结果是通过回调函数的参数返回的
fs.open(path, flags[, mode], callback)
参数:
- path:待打开文件的路径,如:C:\\Users\\Administrator\\hello.txxt
- flags:打开文件要做的操作的类型。r表示只读;w表示只写。
- mode:可选参数,设置文件的操作权限,一般不传。
- callback:回调函数,该回调函数有两个参数:
- err:错误对象,如果没有错误则为null
- fd:文件的描述符
第二步,向文件中写入内容
fs.write(fd, string[, position[, encoding]], callback)
参数:
- fd:文件的描述符,通常传入open()方法的返回的文件描述符对象
- string:待写入的内容
- position:可选参数,表示在文件中写入的起始位置
- encoding:可选参数,写入编码,默认为utf-8
- callback:回调函数,该回调函数有一个参数:
- err:错误对象,如果没有错误则为null
第三步,保存并关闭文件对象
fs.close(fd, callback)
参数:
- fd:文件的描述符
- callback:回调函数,该回调函数有一个参数:
- err:错误对象,如果没有错误则为null
例如:
// 第零步,导入fs模块
var fs = require("fs");
// 第一步,打开文件,异步调用的方法结果是通过回调函数的参数返回的
fs.open("hello.txt", "w", function (err, fd) {
// 不能用"err!=null"来进行判断
if (!err) {
// 第二步,向文件中写入内容
fs.write(fd, "这是同步方式向文件写入的内容。", function (err) {
if (!err) {
console.log("写入成功!")
}
// 第三步,保存并关闭文件对象
fs.close(fd, function (err) {
if (!err) {
console.log("关闭成功!")
} else {
console.log("关闭失败,error: " + err)
}
})
});
} else {
console.log(err);
}
});
简单文件写入
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,调用writeFile或writeFileSync方法向文件中写入内容
writeFileSync(file, data[, options]):同步写入
参数:
- file:要写入文件的路径
- data:待写入的数据
- options:可选项,是一个对象,可以对写入操作进行一些设置
writeFile(file, data[, options], callback):异步写入
参数:
- file:要写入文件的路径
- data:待写入的数据
- options:可选项,是一个对象,可以对写入操作进行一些设置
- callback:当写入完成后执行的回调函数。有一个参数err:
- err:错误对象,如果没有错误则为null
例如:
// 第零步,引入fs模块
var fs = require("fs");
// 第一步,简单文件写入
fs.writeFile("hello.txt", "这是通过简单文件方式写入的数据内容。", function (err) {
if (!err) {
console.log("写入成功!");
} else {
console.log("写入失败!");
}
});
// 或者通过writeFileSync方法写入,并添加options参数
fs.writeFileSync("hello.txt", "这是通过简单文件方式写入的数据内容。", {flag: "a"});
打开状态可以选用的值:
流式文件写入
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,调用createWriteStream方法创建一个可写流
var ws = fs.createWriteStream(path[, options]);
- 参数:
- path:文件路径
- options:可选参数,待配置的参数
- 返回值:
- 返回一个可写流对象
第二步,调用可写流对象的write方法向文件中输出内容
ws.write(data);
- 参数:
- data:待向文件写入的内容
第三步,关闭流对象使用end()方法而非close()方法
ws.end();
其他方法:监听流的open和close事件来监听流的打开和关闭
ws.on(事件字符串, 回调函数):可以为对象绑定一个事件。
ws.once(事件字符串, 回调函数):可以为对象绑定一个一次性的事件,该事件将会在触发一次后自动失效
例如:
// 第零步,引入fs模块
var fs = require("fs");
// 第一步,创建一个可写流
var ws = fs.createWriteStream("hello.txt");
// 第二步,向文件中写入内容
ws.write("第一行内容。\n");
ws.write("第二行内容。\n");
ws.write("第三行内容。\n");
ws.write("第四行内容。\n");
// 第三步,关闭流对象
ws.end();
// 监听流的打开
ws.once("open", function () {
console.log("流打开了...");
});
// 监听流的关闭
ws.once("close", function () {
console.log("流关闭了...");
});
文件的读取
同步文件读取
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,打开文件
var fd = fs.openSync(path, flags[, mode]);
参数:
- path:待打开文件的路径,如:C:\\Users\\Administrator\\hello.txxt
- flags:打开文件要做的操作的类型。r表示只读;w表示只写。
- mode:可选参数,设置文件的操作权限,一般不传。
返回值:
- 该方法会返回一个文件描述符作为结果,我们可以通过该描述对文件进行各种操作
第二步,向文件中写入内容
fs.readSync(fd, buffer, offset, length, position);
参数:
- fd:文件的描述符,通常传入openSync()方法的返回值
- buffer:数据将写入的缓冲区
- offset:要写入数据的 buffer 中的位置
- length:读取的字节数
- position:指定从文件中开始读取的位置
返回值:
- 返回阅读的字节数
第三步,保存并关闭文件对象
fs.closeSync(fd)
参数:
- fd:待关闭文件的描述符
例如:
// 第零步,导入fs模块
var fs = require("fs");
// 第一步,打开文件
var fd = fs.openSync("D:\\NodeJs\\node-demo\\hello.txt", "r");
console.log(fd);
// 第二步,从文件中读取内容
var buffer = Buffer.alloc(1024);
var len = fs.readSync(fd, buffer, 0, buffer.length, 0);
// 打印缓冲区中的内容
console.log(buffer.toString());
异步文件读取
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,打开文件,异步调用的方法结果是通过回调函数的参数返回的
fs.open(path, flags[, mode], callback)
参数:
- path:待打开文件的路径,如:C:\\Users\\Administrator\\hello.txxt
- flags:打开文件要做的操作的类型。r表示只读;w表示只写。
- mode:可选参数,设置文件的操作权限,一般不传。
- callback:回调函数,该回调函数有两个参数:
- err:错误对象,如果没有错误则为null
- fd:文件的描述符
第二步,从文件中读取内容
fs.read(fd, buffer, offset, length, position, callback)
参数:
- fd:文件的描述符,通常传入open()方法的返回的文件描述符对象
- buffer:数据将写入的缓冲区
- offset:要写入数据的 buffer 中的位置
- length:读取的字节数
- position:指定从文件中开始读取的位置
- callback:回调函数,该回调函数有三个参数:
- err:错误对象,如果没有错误则为null
- bytesRead:阅读的字节数
- buffer:写入了数据的缓冲区
第三步,保存并关闭文件对象
fs.close(fd, callback)
参数:
- fd:文件的描述符
- callback:回调函数,该回调函数有一个参数:
- err:错误对象,如果没有错误则为null
实例如下:
// 第零步,引入fs模块
var fs = require("fs");
// 第一步,打开文件
fs.open("hello.txt", "r", function (err, fd) {
if (!err) {
// 第二步,从文件中读取内容
var buf = Buffer.alloc(1024);
fs.read(fd, buf, 0, buf.length, 0, function (err, bytesRead, buffer) {
if (!err) {
console.log(buffer.toString());
// 第三步,关闭流
fs.close(fd, function (err) {
if (!err) {
console.log("关闭流成功!");
} else {
console.log("关闭流失败!");
}
});
}
});
}
});
简单文件读取
步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,调用readFile或readFileSync方法从文件中读取内容
readFileSync(path[, options]):同步读取
参数:
- path:要读取的文件的路径
- options:可选项,是一个对象,可以对读取操作进行一些设置
返回值:
- 返回读取到的数据,是一个Buffer
readFile(path[, options], callback):异步读取
参数:
- path:要读取的文件的路径
- options:可选项,是一个对象,可以对读取操作进行一些设置
- callback:当读取完成后执行的回调函数。有两个参数:
- err:错误对象,如果没有错误则为null
- data:读取到的数据,会返回一个Buffer
实例如下:
// 第零步,导入fs模块
var fs = require("fs");
// 第一步,调用readFile或readFileSync方法从文件中读取内容
var buffer = fs.readFileSync("hello.txt");
console.log(buffer.toString());
// 或者通过readFile方法
fs.readFile("hello.txt", function (err, data) {
if (!err) {
console.log(data.toString());
}
});
流式文件读取
简单文件读取会读取所有的数据在内存中,如果是大文件很可能造成内存崩溃,所以使用流式读取大文件。步骤如下:
第零步,导入fs模块
var fs = require("fs");
第一步,调用createReadStream方法创建一个可读流
var rs = fs.createReadStream(path[, options]);
参数:
- path:文件路径
- options:可选参数,待配置的参数
返回值:
- 返回一个可读流对象
第二步,如果要读取一个可读流中的数据,必须为可读流绑定一个data事件,data事件绑定完毕,它会自动开始读取数据
rs.on("data", callback);
参数:
- "data":固定值
- callback:回调函数。一个参数data:
- data:从可读流中读取到的数据,是一个Buffer
第三步,关闭流对象,并且是监听close事件关闭
rs.once("close", function() {
rs.close();
});
其他方法:监听流的open和close事件来监听流的打开和关闭
ws.on(事件字符串, 回调函数):可以为对象绑定一个事件。
ws.once(事件字符串, 回调函数):可以为对象绑定一个一次性的事件,该事件将会在触发一次后自动失效
实例如下:
// 第零步,导入fs模块
var fs = require("fs");
// 第一步,调用createReadStream方法创建一个可读流
var rs = fs.createReadStream("hello.txt");
// 第二步,如果要读取一个可读流中的数据,必须为可读流绑定一个data事件,data事件绑定完毕,它会自动开始读取数据
rs.once("data", function (data) {
console.log(data.toString());
});
// 第三步,关闭流对象使用end()方法而非close()方法,并且是监听close事件关闭
rs.once("close", function () {
console.log("关闭流成功!");
rs.close();
});
可读流数据写入到可写流
- 第一种方式:
/*
第一种方式
*/
// 从可读流中读取数据然后通过可写流写入数据
// 导入fs模块
var fs = require("fs");
// 创建可读流
var rs = fs.createReadStream("hello.txt");
// 创建可写流
var ws = fs.createWriteStream("hello-copy.txt");
// 监听流的开启和关闭
rs.once("open", function () {
console.log("可读流打开了...");
});
rs.once("close", function () {
console.log("可读流关闭了...");
ws.end();
});
ws.once("open", function () {
console.log("可写流打开了...");
});
ws.once("close", function () {
console.log("可写流关闭了...");
});
// 将从可读流中读取的数据通过可写流写入
rs.on("data", function (data) {
ws.write(data);
});
- 第二种方式
/*
第二种方式
*/
// 从可读流中读取数据然后通过可写流写入数据
// 导入fs模块
var fs = require("fs");
// 创建可读流
var rs = fs.createReadStream("hello.txt");
// 创建可写流
var ws = fs.createWriteStream("hello-copy.txt");
// pipe()方法可以将可读流中的内容,直接输出到可写流
rs.pipe(ws);
其他方法
var fs = require("fs");
/*
通过检查文件系统来测试给定的路径是否存在:
fs.exists(path, callback);
参数:
- path:待判断的路径
- callback:回调函数。有一个参数exists:
- exists:布尔值,即路径是否存在的结果
fs.existsSync(path);
返回值:
- 返回尔值,即路径是否存在的结果
*/
fs.exists("D:\\abc\\text.txt", function (exists) {
if (exists) {
console.log("路径存在!");
} else {
console.log("路径不存在");
}
});
var existsSync = fs.existsSync("D:\\abc\\text.txt");
console.log("路径是否存在:" + existsSync);
/*
获取文件信息:
fs.stat(path[, options], callback)
参数:
- path:文件路径
- options:可选参数,可设置一些选项,如bigint
- callback:回调函数,有两个参数:
- err:错误对象
- stats:文件信息对象
fs.statSync(path[, options])
参数:
- path:文件路径
- options:可选参数,可设置一些选项,如bigint
返回值:
- 返回文件信息对象Stats
*/
fs.stat("D:\\jobs.sql", function (err, stats) {
if (!err) {
console.log(stats);// 打印Stats对象
console.log(stats.size);// 文件大小
}
});
var statSync = fs.statSync("D:\\jobs.sql");
console.log(statSync);
/*
删除文件,如果文件不存在则会报错(不适用于目录,无论是空目录还是其他目录。):
fs.unlink(path, callback);
参数:
- path:文件路径
- callback:回调参数。有一个参数err:
- err:错误对象
fs.unlinkSync(path);
参数:
- path:文件路径
*/
fs.unlink("D:\\hello.txt", function (err) {
if (!err) {
console.log("删除成功!");
}
});
// fs.unlinkSync("D:\\hello.txt");
/*
列出目录下的文件
fs.readdir(path[, options], callback);
参数:
- path:目录路径
- options:可选项,可以设置encoding、withFileTypes
- callback:回调函数,有两个参数err和files:
- err:错误对象
- files:是目录中文件名的数组,不包括 '.' 和 '..'
fs.readdirSync(path[, options]);
参数:
- path:目录路径
- options:可选项,可以设置encoding、withFileTypes
返回值:
- 返回目录中文件名的数组
*/
fs.readdir("C:\\", function (err, files) {
if (!err) {
console.log(files);
}
});
var filesSync = fs.readdirSync("C:\\");
console.log(filesSync.length);
/*
创建目录
fs.mkdir(path[, options], callback);
参数:
- path:目录路径
- options:可选项,可以设置recursive和mode,是一个Object
- callback:回调函数,有一个参数err:
- err:错误对象
fs.mkdirSync(path[, options]);
参数:
- path:目录路径
- options:可选项,可以设置recursive和mode,是一个Object
返回值:
- 返回 undefined 或创建的第一个目录路径(如果 recursive 为 true)
*/
fs.mkdir("C:\\abc\\123", {recursive: true}, function (err) {
if (!err) {
console.log("创建目录成功!")
}
});
var path = fs.mkdirSync("C:\\abc\\456", {recursive: true});
console.log(path);
/*
截断文件,即只保存指定字节长度的文件内容
fs.truncate(path[, len], callback);
参数:
- path:文件路径
- len:可选项,默认为0
- callback:回调函数,只有一个参数err:
- err:错误对象
fs.truncateSync(path[, len]);
参数:
- path:文件路径
- len:可选项,默认为0表示将文件清空
*/
fs.truncate("D:\\NodeJs\\node-demo\\hello.txt", 5, function (err) {
if (!err) {
console.log("截断文件成功!");
}
});
fs.truncateSync("D:\\NodeJs\\node-demo\\hello.txt");
/*
删除目录
fs.rmdir(path[, options], callback);
参数:
- path:待删除目录的路径
- options:可选项,可以设置maxRetries、recursive、retryDelay,是一个Object
- callback:回调函数,有一个err参数:
- err:错误对象
fs.rmdirSync(path[, options]);
参数:
- path:待删除目录的路径
- options:可选项,可以设置maxRetries、recursive、retryDelay,是一个Object
*/
fs.rmdir("C:\\abc\\123", function (err) {
if (!err) {
console.log("删除目录成功!")
}
});
fs.rmdirSync("C:\\abc\\456");
/*
重命名文件和目录,如果oldPath和newPath相同则是重命名,否则就是将文件从oldPath剪切到newPath
fs.rename(oldPath, newPath, callback);
参数:
- oldPath:旧文件或目录路径名
- newPath:新文件或目录路径名,如果已经存在则会被覆盖
- callback:回调参数,有一个err参数:
- err:错误对象Error
fs.renameSync(oldPath, newPath);
参数:
- oldPath:旧文件或目录路径名
- newPath:新文件或目录路径名,如果已经存在则会被覆盖
*/
fs.renameSync("hello2.txt", "hello-rename.txt");
fs.rename("hello-rename.txt", "hello2.txt", function (err) {
if (!err) {
console.log("重命名成功!");
}
});
/*
监视 filename 的变化。 每次访问文件时都会调用回调 listener
fs.watchFile(filename[, options], listener);
参数:
- filename:文件或目录路径
- options:可选参数,可指定bigint、persistent、interval(指定每隔多少时间轮询检查文件是否被修改),是一个Object
- listener:监听函数,有两个参数current和previous:
- current:文件修改之后的状态,是一个Stats对象
- previous:文件修改之前的状态,是一个Stats对象
返回值:
- 返回StatWatcher
*/
fs.watchFile("hello.txt", {interval: 1000}, function (curr, prev) {
console.log("修改前文件大小:" + prev.size);
console.log("修改后文件大小:" + curr.size);
});