node基本模块使用

模块分类

  • 自定义模块
  • 系统核心模块
  • fs 文件操作
  • http 网络操作
  • path 路径操作
  • querystring 查询参数解析
  • url url解析

1.导出和导入

在NodeJS中,每个js文件就是一个模块,而文件路径就是模块名, 在编写每个模块时,都有require、exports、module三个预先定义好的变量可供使用。

require函数用于在当前模块中加载和使用别的模块,其中js扩展名可省略,require多次不会重复初始化,如果传递给require函数的是NodeJS内置模块名称,不做路径解析,require(‘express’);

exports对象是当前模块的导出对象,用于导出模块公有方法和属性。别的模块通过require函数使用当前模块时得到的就是当前模块的exports对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9h4v0DOA-1584629969149)(img/模块.png)]

导入导出结合使用:

var sum = function (a,b) {
    return parseInt(a) + parseInt(b);
}


// 导出模块
// exports.sum = sum;


// module导出成员的方式   导出的是单独的方法
module.exports = sum;
/* 引入模块 */
var module = require("./01");

/* var ret = module.sum(2, 3);
console.log(ret) */

var ret = module(7, 8);
console.log(ret);

__filename获取当前模块文件的带有完整绝对路径的文件名。

__dirname获得当前文件所在目录的完整目录名

2、path模块

路径操作

  • 路径基本操作API
    path 模块提供用于处理文件路径和目录路径的实用工具。 它可以使用以下方式访问:
const path = require('path');
  • path.basename(path[, ext])

path.basename(path[, ext])

path < string >

ext < string > 可选的文件扩展名。 加上的话会把扩展名去掉,只留下文件名

返回: < string >

path.basename() 方法返回 path 的最后一部分, 类似于 Unix 的 basename 命令。 尾部的目录分隔符将被忽略。

// 获取路径的最后一部分(最后的文件名 + 扩展名)
path.basename(path[, ext])
console.log(path.basename('/foo/bar/baz/asdf/quux.html')); // quux.html
console.log(path.basename('/foo/bar/baz/asdf/quux.html', '.html')); // quux
  • path.dirname(path)

path : < string >

返回: < string >

path.dirname() 方法返回 path 的目录名,类似于 Unix 的 dirname 命令。 尾部的目录分隔符将被忽略.

path.dirname('/foo/bar/baz/asdf/quux.txt');
// 返回: '/foo/bar/baz/asdf'
  • path.extname(path)
    path < string >
    返回: < string >
    path.extname() 方法返回 path 的扩展名, 从最后一次出现.(句点) 字符到 path 最后一部分的字符 串结束。 如果在 path 的最后一部分中没有.,或者如果 path 的基本名称( 参阅 path.basename()) 除了第一个字符以外没有.,则返回空字符串。
path.extname('index.html');
// 返回: '.html'

path.extname('index.coffee.md');
// 返回: '.md'

path.extname('index.');
// 返回: '.'

path.extname('index');
// 返回: ''

path.extname('.index');
// 返回: ''

path.extname('.index.md');
// 返回: '.md'
  • path.format(pathObject)

pathObject < Object >

dir < string >

root < string >

base < string >

name < string >

ext < string >

返回: < string >

path.format() 方法从对象返回路径字符串。 与 path.parse() 相反。

当为 pathObject 提供属性时, 注意以下组合, 其中一些属性优先于另一些属性:

如果提供了 pathObject.dir, 则忽略 pathObject.root。

如果 pathObject.base 存在, 则忽略 pathObject.ext 和 pathObject.name。

  • path.parse(path)
路径的格式化处理
// path.format()  obj -> string
// path.parse()   string->obj
let obj = path.parse(__filename);
console.log(obj);
/* 
{
    root: '/',  文件的根路径
    dir: '/Users/liqi/Desktop/jiyun/nodejs/未命名文件夹/03-node基础', 文件的全路径
    base: '02.js', 文件的名称
    ext: '.js', 扩展名
    name: '02' 文件的名称 
}
*/

let objpath = {
    root: "/",
    dir: "/Users/aaa/bbb/ccc",
    base: "abc.txt",
    ext: ".txt",
    name: "abc"
}
let strpath = path.format(objpath);
console.log(strpath); // /Users/aaa/bbb/ccc/abc.txt
  • path.isAbsolute(path)

path < string >

返回: < boolean >

path.isAbsolute() 方法检测 path 是否为绝对路径。

如果给定的 path 是零长度字符串, 则返回 false。

// 在 POSIX 上:
path.isAbsolute('/foo/bar'); // true
path.isAbsolute('/baz/..');  // true
path.isAbsolute('qux/');     // false
path.isAbsolute('.');        // false

// 在 Windows 上
path.isAbsolute('//server');    // true
path.isAbsolute('\\\\server');  // true
path.isAbsolute('C:/foo/..');   // true
path.isAbsolute('C:\\foo\\..'); // true
path.isAbsolute('bar\\baz');    // false
path.isAbsolute('bar/baz');     // false
path.isAbsolute('.');           // false
  • path.join([…paths])

…paths < string > 路径片段的序列。

返回: < string >

path.join() 方法使用平台特定的分隔符作为定界符将所有给定的 path 片段连接在一起, 然后规范化生成的路径。

零长度的 path 片段会被忽略。 如果连接的路径字符串是零长度的字符串, 则返回 ‘.’,

表示当前工作目录。

// 拼接路径 (..表示上层路径; .表示当前路径),在连接路径的时候会规范化路径

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'
  • path.normalize(path)

path < string >

返回: < string >

path.normalize() 方法规范化给定的 path, 解析 ‘…’ 和 '.'片段。

当找到多个连续的路径段分隔字符时( 例如 POSIX 上的 / 、Windows 上的\ 或 / ),则它们将被替换为单个平台特定的路径段分隔符( POSIX 上的 / 、Windows 上的\)。 尾部的分隔符会保留。

如果 path 是零长度的字符串, 则返回 ‘.’,表示当前工作目录

// 在 POSIX 上:
path.normalize('/foo/bar//baz/asdf/quux/..');
// 返回: '/foo/bar/baz/asdf'

// 在 Windows 上:
path.normalize('C:\\temp\\\\foo\\bar\\..\\');
// 返回: 'C:\\temp\\foo\\'

//由于 Windows 识别多种路径分隔符,因此这些分隔符都将被替换为 Windows 首选的分隔符(\):
path.win32.normalize('C:temp\\\\/\\/\\/foo/bar');
// 返回: 'C:\\temp\\foo\\bar'
  • path.posix
  • path.relative(from, to)

from < string >

to < string >

返回: < string >

path.relative() 方法根据当前工作目录返回 from 到 to 的相对路径。 如果 from 和 to 各自解析到相同的路径( 分别调用 path.resolve() 之后), 则返回零长度的字符串。

如果将零长度的字符串传入 from 或 to, 则使用当前工作目录代替该零长度的字符串。

// 计算相对路径

// 在 POSIX 上:
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
// 返回: '../../impl/bbb'

// 在 Windows 上:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb');
// 返回: '..\\..\\impl\\bbb'
  • path.resolve([…paths])

…paths < string > 路径或路径片段的序列。

返回: < string >

path.resolve() 方法将路径或路径片段的序列解析为绝对路径。

给定的路径序列从右到左进行处理, 每个后续的 path 前置, 直到构造出一个绝对路径。 例如, 给定的路径片段序列: / foo、 / bar、 baz, 调用 path.resolve(’/foo’, ‘/bar’, ‘baz’) 将返回 / bar / baz。

如果在处理完所有给定的 path 片段之后还未生成绝对路径, 则再加上当前工作目录。

生成的路径已规范化, 并且除非将路径解析为根目录, 否则将删除尾部斜杠。

零长度的 path 片段会被忽略。

如果没有传入 path 片段, 则 path.resolve() 将返回当前工作目录的绝对路径。

// 解析路径

path.resolve('/foo/bar', './baz');
// 返回: '/foo/bar/baz'

path.resolve('/foo/bar', '/tmp/file/');
// 返回: '/tmp/file'

path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果当前工作目录是 /home/myself/node,
// 则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
  • path.sep

< string >

提供平台特定的路径片段分隔符:

Windows 上是\。

POSIX 上是 /

console.log(path.delimiter); //  表示变量分隔符 (windows 中使用;  Linux中使用:)
console.log(path.sep);    // /   表示路径分隔符(windows 是 \ ; Linux  是 /)
  • path.delimiter

< string >

提供平台特定的路径定界符:

  • 用于 POSIX
  • path.toNamespacedPath(path)
  • path.win32

3、fs模块

文件操作

带sync的都是同步的方法,不带sync的都是异步的方法

  • 文件信息获取

dirent.isDirectory()

返回: < boolean >

如果 fs.Dirent 对象描述文件系统目录, 则返回 true。

dirent.isFile()

返回: < boolean >

如果 fs.Dirent 对象描述常规文件, 则返回 true。

fs.stat (path[, options], callback) 返回文件的信息

// 引入fs  文件系统
const fs = require('fs');
fs.stat("./data.txt", function (err, stat) {
    // 一般回调函数的第一个参数是错误对象,如果err为null,表示没有错误,否则表示报错了
    if (err) return;
    if (stat.isFile()) {
        console.log("文件")
    } else if (stat.isDirectory) {
        console.log("目录")
    }
    console.log(stat);
    /* 
        atime  访问时间 (access )
        ctime  修改时间( change 文件的状态发生变化的时候, 权限)
        mtime  文件数据发生变化的时间(modified 当文件的数据被修改的时候)
        birthtime 创建时间
    */
         
})
  • 读文件操作
const fs = require("fs");
const path = require("path");

let strpath = path.join(__dirname, "data.txt");
/* fs.readFile(strpath, (err, data) => {
    if (err) return;
    console.log(data); // <Buffer 31 39 30 39 41>  1909A
    console.log(data.toString()); // 1909A
}) */

// 如果有第二个参数并且是编码,n那么回调函数获取到的数据就是字符串
// 如果没有第二个参数,那么得到的就是Buffer实例对象
fs.readFile(strpath,"utf8", (err, data) => {
    if (err) return;
    console.log(data); //   1909A
})

// 同步操作
let ret = fs.readFileSync(strpath, "utf8");
console.log(ret);
  • 写文件操作
/* 
    写文件操作

    fs.writeFile(file, data[, options], callback)
    fs.writeFileSync(file, data[, options])
*/

const fs = require("fs");
const path = require("path");

let strpath = path.join(__dirname, "data.txt");
// 异步写入文件
/* 
// 写入字符串
fs.writeFile(strpath, "hello nihao", (err) => {
    console.log(err);
    if(!err){
        console.log("文件写入成功")
    }
}) 
*/

/* 
// 写入buffer
let buf = Buffer.from("hi");
fs.writeFile(strpath, buf, (err) => {
    if (!err) {
        console.log("文件写入成功")
    }
})
*/


// 同步写入文件
fs.writeFileSync(strpath, "tom and jerry");
  • 大文件操作
// =========================================================
/* 
    大文件操作(流式操作)
*/
// fs.createReadStream(path[, options])
// fs.createWriteStream(path[, options])

const path = require("path");
const fs = require("fs");

let spath = path.join(__dirname, "file.zip");
let dpath = path.join("/Users/liqi/Desktop", "file.zip");

// 读取文件的数据流
let readStream = fs.createReadStream(spath);
// 写文件的数据流
let writeStream = fs.createWriteStream(dpath);

// 基于事件的处理方式 事件驱动程序 data事件
// chunk  是一块数据   每读取一块数据就调用一下data
/* 
let num = 1;
readStream.on("data", (chunk) => {
    num++;
    writeStream.write(chunk);
})

// 什么时候读取完呢   end事件
readStream.on("end", () => {
    console.log("文件处理完成" + num);
}) */

// --------------------------------------------

// 另外一种语法  pipe 管道   读取流和写入流连接到一块  读的数据直接传给写的入口
readStream.pipe(writeStream);
  • 目录操作
/* 
    目录操作
    1、创建目录
        fs.mkdir(path[, options], callback)
        fs.mkdirSync(path[, options])
    2、读取目录
        fs.readdir(path[, options], callback)
        fs.readdirSync(path[, options])
    3、删除目录
        fs.rmdir(path[, options], callback)
        fs.rmdirSync(path[, options])

*/

const path = require("path");
const fs = require("fs");

// 创建目录   异步的方式
//    第一个参数是创建目录的路径  对应的回调函数就一个参数  err 错误回调
/* 
fs.mkdir(path.join(__dirname, "abc"), (err) => {
    console.log(err)
}); 
*/

// 创建目录  同步方式
// fs.mkdirSync(path.join(__dirname, "hello"));

// ---------------------------------------------------

// 读取目录  异步
/* 
fs.readdir(__dirname, (err, files) => {
    console.log(files); // [ '01.js','02.js','03.js','04.js','05.js','06.js','07.js','08.js','abc','data.txt','file.zip','hello']
    files.forEach((item, index) => {
        fs.stat(path.join(__dirname, item), (err, stat) => {
            if (stat.isFile()) {
                console.log(item,"文件")
            } else if (stat.isDirectory()) {
                console.log(item,"目录")
            }
        })
    })
})
*/


 
// 读取目录 同步
let files = fs.readdirSync(__dirname);
files.forEach((item, index) => {
    fs.stat(path.join(__dirname, item), (err, stat) => {
        if (stat.isFile()) {
            console.log(item, "文件")
        } else if (stat.isDirectory()) {
            console.log(item, "目录")
        }
    })
})

// --------------------------------------

// 删除目录 异步
// fs.rmdir(path.join(__dirname, "abc"), (err) => {
//     console.log(err);
// })

// 删除目录  同步
fs.rmdirSync(path.join(__dirname,"hello"));