Node.js学习笔记

笔记来自于视频:尚硅谷-快速入门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");

注意:两种方式不能同时使用,否则会报错。关于exportsmodule.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):将一个字符串转换成buffer
  • Buffer.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);
});
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值