1. File System(fs)模块:
      文件和文件夹的操作模块,主要对两部分进行操作,一个是文件,另一个是文件夹。
      const _fs = require(‘fs’);

    1.1 新建文件夹:
    1.1.1 异步写法:_fs.mkdir(path,[options],callback);
    // 第一个参数是地址,创建的文件夹存放的地址;
    // 第二个参数不是必填参数,可以是一个整数用来指定文件的模式(权限与粘滞位);也可以是一个对象,其中recursive属性是否创建父目录;
    // 第三个参数是回调函数,参数就是error的错误

    1. _fs.mkdir('/tmp/a/apple',{recursive:true},(err)=>{if(err)throw err})
    2. 异步都有回调函数,在node中,回调函数都有一个规范,错误优先的原则,回调函数的第一个参数都是err
    3. 表示是不是错误,默认的都是null,没有错误。

    1.1.2 同步写法:_fs.mkdirSync(path,[options]);
    如果调用出错,都会终止执行,必须要用try catch捕获错误。

    1. try{
    2. let result=mkdirSync("./test2");
    3. }catch(e){
    4. console.log(new Error("错误"));
    5. }

    1.2 删除文件夹:
    1.2.1 异步写法:_fs.rmdir(path,callback);
    1.2.2 同步写法:_fs.rmdirSync(path);
    1.3 读取文件夹:
    1.3.1 异步写法:_fs.readdir(path,[options],callback);
    // 读取文件夹的时候,回调函数会有两个参数,一个是错误,一个是读取的文件;
    // 如果options是一个字符串,则指定字符编码。
    如果encoding设为‘buffer’,则返回的文件名是Buffer,可以定义为uth-8;

    1. _fs.readdir('./test',(err,file)=>{
    2. console.log(err);
    3. console.log(file); // 文件夹中的文件,以数组的形式存放
    4. })

    1.3.2 同步写法:_fs.readdirSync(path[, options])

    1.4 判断是否为文件或者文件夹:_fs.stat(path,[options],callback);

    1. /*1. callback 有两个参数 (err, stats),其中 stats 是一个 fs.Stats。
    2. 2. 如果发生错误,则 err.code 会是常见系统错误之一。
    3. 3. 不建议在调用 fs.open()、fs.readFile() 或 fs.writeFile() 之前使用 fs.stat() 检查文件是否存在。
    4. 应该直接打开、读取或写入文件,当文件无效时再处理错误。
    5. 4. 如果要检查文件是否存在但不操作它,建议使用 fs.access()。*/
    6. fs.stat("./test2",(err,state)=>{
    7. err:错误
    8. state.isFile(); 状态是否是文件,返回值为布尔值
    9. state.isDirectory(); 状态是否是文件夹,返回值为布尔值
    10. })

    1.5 新建文件:fs.writeFile(file, data[, options], callback);
    1.6 写入(持续)文件:不覆盖文件
    fs.appendFile(“./file.txt”,data,(err)=>{

    1. console.log(err);

    })
    1.7 删除文件:
    fs.unlink(path,callback);

    fs.unlink(“./file.txt”,(err)=>{

    1. console.log(err);

    })
    1.8 读取文件:fs.readFile(file,callback);
    // callback回调函数中有两个参数,一个是err,另一个是data,读取的数据,一般data的格式都要改变,两种方法:

    1. 可以写成data.toString;
    2. 可以调用方法的时候多加一个参数,改变数值类型的(file,”utf8”,callback);

    3. URL模块
      2.1 将一个url地址变成一个对象。
      url.parse(urlString,[opotion]);
      // 第一个参数填的是url地址;
      // 第二个参数默认是false,如果设置成true,就可以将URL组成的query转成对象的形式;
      // 第三个参数默认是false,如果设置成true,就可以解析前面没有协议的地址,不然就得不到端口号等;
      2.2 将对象(格式正确)转化为一个URL地址
      url.format(URL,[options]);
      options
      auth 如果序列化的URL字符串应该包含用户名和密码为true,否则为false。默认为true。
      fragment 如果序列化的URL字符串应该包含分段为true,否则为false。默认为true。
      search 如果序列化的URL字符串应该包含搜索查询为true,否则为false。默认为true。
      unicode true 如果出现在URL字符串主机元素里的Unicode字符应该被直接编码而不是
      使用Punycode编码为true,默认为false。 ```javascript

      const { URL } = require(‘url’); const myURL = new URL(‘https://a:b@你好你好?abc#foo‘);

      console.log(myURL.href); // 输出 https://a:b@xn--6qqa088eba/?abc#foo

      console.log(myURL.toString()); // 输出 https://a:b@xn--6qqa088eba/?abc#foo

      console.log(url.format(myURL, { fragment: false, unicode: true, auth: false })); // 输出 ‘https://你好你好/?abc

      1. 3. **queryString模块**<br />就是查询字符串,模块提供了一些实用的函数,用于解析与格式化URL查询字符串。<br />(专门处理形如 key1=value1&key2=value2 这种格式的数据的)
      2. 方法:3.1. querystring.escape(str): 对给定的str进行URL编码;
      3. 2. querystring.unescape(str): 对给定的str进行URL编码;
      4. 3. querystring.stringify(obj,[sep],[eq],[options]): 将对象转化为字符串;
      5. sep:第二个参数,用于界定查询字符串中的键值对的子字符串。默认为 '&'。<br />eq 第三个参数 用于界定查询字符串中的键与值的子字符串。默认为 '='。<br />options:<br />encodeURIComponent [<Function>](http://nodejs.cn/s/_moz/Reference/Global_Objects/Function) 把对象中的字符转换成查询字符串时使用的函数。默认为 querystring.escape()。该方法通过遍历给定的 obj 对象的自身属性,生成 URL 查询字符串。
      6. ```javascript
      7. // 假设存在 gbkEncodeURIComponent 函数。
      8. querystring.stringify(
      9. { w: '中文', foo: 'bar' },
      10. null,
      11. null,
      12. { encodeURIComponent: gbkEncodeURIComponent }
      13. );

      3.4 querystring.parse(str,sep,eq,options): 将query字符串转化为对象。
      sep 第二个参数 用于界定查询字符串中的键值对的子字符串。默认为 ‘&’。
      eq 第三个参数 用于界定查询字符串中的键与值的子字符串。默认为 ‘=’。
      options
      decodeURIComponent 解码查询字符串的字符时使用的函数。默认为 querystring.unescape()。
      maxKeys 指定要解析的键的最大数量。指定为 0 则不限制。默认为 1000。

      1. path模块
        dirname 表示的是获取当前文件所在目录的绝对路径;
        path模块通常会和fs模块配合使用,然后fs模块写路径是配合path模块的方法就变成了绝对路径。
        方法:4.1 path.join.([…paths]): 路径的拼接。智能拼接,通常配合
        dirname使用生成绝对路径;
        4.2 path.resolve([…path]): 把一个路径或路径片段的序列解析为一个绝对路径,/被解析为根目录
        两者区别:对于以 / 开始的路径片段,path.join 只是简单的将该路径片段进行拼接,而 path.resolve 将以 / 开始的路径片段作为根目录,在此之前的路径将会被丢弃。
        4.3 path.isAbsolute(path): 判断path是否绝对路径,返回值为boolean;
        4.4 path.dirname(path): 获取一个路径中的文件夹名;
        4.5 path.basename(path): 获取一个路径中的文件名;
        4.6 path.extname(path): 返回 path 的扩展名,即从 path 的最后一部分中的最后一个 .(句号)字符到字符串结束。 如果 path 的最后一部分没有 . 或 path 的文件名(参考 path.basename())的第一个字符是 .,则返回一个空字符串

      2. dirname 与 filename
        dirname 、filename 是每个模块文件中默认存在的变量,可以直接使用不需要引入。
        __dirname: 当前模块的目录名;
        __filename: 当前模块的文件名。

      3. zlib模块
        zlib就是文档压缩,zlib模块提供通过 Gzip 和 Deflate/Inflate 实现的压缩功能。 ```javascript //压缩或者解压数据流(例如一个文件)通过zlib流将源数据流传输到目标流中来完成; const gzip = zlib.createGzip(); const fs = require(‘fs’); const inp = fs.createReadStream(‘input.txt’); const out = fs.createWriteStream(‘input.txt.gz’);

      inp.pipe(gzip).pipe(out);

      1. 7. **Stream--流**<br />几乎所有的Node.js应用都在某种程度上使用了流,流就是一种数据的传输方式。<br />let read = fs.createReadStream('./events.js') // 创建可读的流<br />let writestream = fs.createWriteStream('./events3.js') // 创建可写的流<br />三种copy的模式:
      2. ```javascript
      3. //整体写入
      4. let data=''
      5. read.on('data',(chunk)=>{
      6. data+=chunk
      7. console.log(chunk)
      8. })
      9. read.on('end',()=>{
      10. fs.writeFileSync('./events2.js', data);
      11. })
      1. //读写流配合
      2. const fs=require('fs')
      3. let read=fs.createReadStream('./events.js')// 创建可读的流
      4. let writestream=fs.createWriteStream('./events3.js')//// 创建可写的流
      5. read.on('data',(chunk)=>{
      6. writestream.write(chunk)
      7. })
      1. //读写流配合pipe
      2. const fs=require('fs')
      3. let read=fs.createReadStream('./events.js')// 创建可读的流
      4. let writestream=fs.createWriteStream('./events4.js')//// 创建可写的流
      5. read.pipe(writestream)
      1. events模块
        events就是事件触发器
        所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上。 事件的命名通常是驼峰式的字符串。 ```javascript

      const EventEmitter = require(‘events’); //引用

      class MyEmitter extends EventEmitter {} //继承

      const myEmitter = new MyEmitter(); //实例化对象

      // 事件的侦听和触发 myEmitter.on(‘event’, () => { console.log(‘触发事件’); });

      myEmitter.emit(‘event’);

      1. ```javascript
      2. /*
      3. 事件移除:1. emitter.removeListener(eventName, listener)单个移除
      4. 从名为 eventName 的事件的监听器数组中移除指定的 listener。
      5. 2. emitter.removeAllListeners([eventName])全部移除;
      6. 移除全部的事件侦听
      7. */
      8. const callback = (stream) => {
      9. console.log('已连接');
      10. };
      11. server.on('connection', callback);
      12. // ...
      13. server.removeListener('connection', callback);
      1. /*
      2. 传参数与 `this` 到监听器:
      3. eventEmitter.emit() 方法可以传任意数量的参数到监听器函数。
      4. 当监听器函数被调用时,this 关键词会被指向监听器所绑定的 EventEmitter 实例。
      5. */
      6. const myEmitter = new MyEmitter();
      7. myEmitter.on('event', function(a, b) {
      8. console.log(a, b, this, this === myEmitter);
      9. // 打印:
      10. // a b MyEmitter {
      11. // domain: null,
      12. // _events: { event: [Function] },
      13. // _eventsCount: 1,
      14. // _maxListeners: undefined } true
      15. });
      16. /*
      17. 也可以使用 ES6 的箭头函数作为监听器,但我们都知道,箭头函数 this 关键词不会指向 EventEmitter 实例,
      18. 但是e.currentTarget是指向实例的
      19. */
      20. const myEmitter = new MyEmitter();
      21. myEmitter.on('event', (a, b) => {
      22. console.log(a, b, this);
      23. // 打印: a b {}
      24. });
      25. myEmitter.emit('event', 'a', 'b');