0


Node.js超详细教程!

0. 基础概念

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,使用了一个事件驱动、非阻塞式 I/O 模型,让 JavaScript 运行在服务端的开发平台。

官方地址:https://nodejs.org/en

中文地址:https://nodejs.org/zh-cn

代码初体验:

console.log("hello NodeJS")

// 1.进入到对应 js 文件的目录下
// 2.执行 node 1-hello.js 
// 3.输出:hello NodeJS

示例代码地址:
https://github.com/chenyl8848/node.js-study

1. Buffer

1.1 概念

Buffer 是一个类似于数组的对象,用于表示固定长度的字节序列。Buffer 本质是一段内存空间,专门用来处理二进制数据。

1.2 特点

  • Buffer 大小固定且无法调整
  • Buffer 性能较好,可以直接对计算机内存进行操作
  • 每个元素的大小为 1 字节(byte)

1.3 使用

1.3.1 Buffer 的创建

Node.js 中创建 Buffer 的方式主要如下几种:

Buffer.alloc

// 创建了一个长度为 10 字节的 Buffer,相当于申请了 10 字节的内存空间,每个字节的值为 0
// 结果为 <Buffer 00 00 00 00 00 00 00 00 00 00>
let buf_1 = Buffer.alloc(10);

Buffer.allocUnsafe

// 创建了一个长度为 10 字节的 Buffer,Buffer 中可能存在旧的数据, 可能会影响执行结果,所以叫 unsafe
let buf_2 = Buffer.allocUnsafe(10);

Buffer.from

// 通过字符串创建 Buffer
let buf_3 = Buffer.from('hello');
// 通过数组创建 Buffer
let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);

1.3.2 Buffer 与字符串的转化

可以借助 toString 方法将 Buffer 转为字符串

// buffer 与字符串的转换
const buffer = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);
// 默认使用 UTF-8 的编码格式 
console.log(buffer.toString())

注意:toString 默认是按照 utf-8 编码方式进行转换的。

1.3.3 Buffer 的操作

Buffer 可以直接通过 [] 的方式对数据进行处理。

const buffer = Buffer.from('hello');
// 二进制:1101000
console.log(buffer[0].toString(2))

// 修改 buffer
buffer[0] = 95
console.log(buffer.toString())

// 溢出 如果修改的数值超过 255 ,则超过 8 位数据会被舍弃
const buffer = Buffer.from('hello')
// 会舍弃高位的数字,因为八位的二进制最高值为 255   0001 0110 1001  => 0110 1001
buffer[0] = 361
console.log(buffer)

// 中文 一个 utf-8 的字符 一般 占 3 个字节
const buffer = Buffer.from('你好')
console.log(buffer)

注意:

如果修改的数值超过255,则超过8位数据会被舍弃 一个 utf-8 的字符一般占3个字节

2. fs 模块

fs 全称为 file system,称之为文件系统,是 Node.js 中的内置模块,可以对计算机中的磁盘进行操作。

2.1 文件写入

文件写入就是将数据保存到文件中,有如下的 API
方法说明writeFile异步写入writeFileSync同步写入appendFile/appendFileSync追加写入createWriteStream流式写入

2.1.1 异步写入

语法: fs.writeFile(file, data, [options], callback)

参数说明:

  • file:文件名
  • data:待写入的数据
  • options:选项设置 (可选)
  • callback:写入回调

返回值: undefined

代码示例:

// 1.导入 fs 模块
const fs = require('fs')

// 2.写入文件
// writeFile 异步写入,四个参数:1.文件路径 2.写入内容 3.配置信息 4.回调函数
// 文件写入成功
fs.writeFile('./座右铭.txt', '封狼居胥,禅于姑衍,饮马瀚海', error => {
    // errror 为 null就是写入成功
    if (error) {
        console.log('文件写入失败')
        return;
    }
    console.log('文件写入成功')
});

2.1.2 同步写入

语法: fs.writeFileSync(file, data, [options]) 参数说明:

  • file:文件名
  • data:待写入的数据
  • options:选项设置 (可选) 返回值: undefined 代码示例:
// 1.导入 fs 模块
const fs = require('fs')

// 2.写入文件
// 同步写入,没有回调函数
fs.writeFileSync('./座右铭.txt', '封狼居胥,禅于姑衍,饮马瀚海,燕石勒然')

Node.js 中的磁盘操作是由其他线程完成的,结果的处理有两种模式:

同步处理:JavaScript 主线程会等待其他线程的执行结果,然后再继续执行主线程的代码,效率较低

异步处理:JavaScript 主线程不会等待其他线程的执行结果,直接执行后续的主线程代码,效率较好

2.1.3 追加写入

appendFile 作用是在文件尾部追加内容,appendFile 语法与 writeFile 语法完全相同

语法:

  • fs.appendFile(file, data, [options], callback)
  • fs.appendFileSync(file, data, [options])

返回值: 二者都为 undefined

代码示例:

// 1.引入 fs 模块
const fs = require('fs');

const content = '\r\n但使龙城飞将在,不教胡马度阴山';

// fs.appendFile('./座右铭.txt', content, error => {
//     // errror 为 null就是写入成功
//     if (error) {
//         console.log('文件追加写入失败')
//         return;
//     }
//     console.log('文件追加写入成功');
// })

// 同步文件追加写入
// fs.appendFileSync('./座右铭.txt', content)

// 使用 writeFile 的方式追加文件写入
fs.writeFile('./座右铭.txt', content, {flag: 'a'}, error => {
    if (error) {
        console.log('文件追加写入失败')
        return;
    }
    console.log('文件追加写入成功')
})

console.log('hello world')

2.1.4 流式写入

语法: fs.createWriteStream(path, [options])

参数说明:

  • path:文件路径
  • options:选项配置( 可选 )

返回值: Object

代码示例:

// 1.导入 fs 模块
const fs = require('fs');

// 2.创建写入流对象
const writeStream = fs.createWriteStream('./观书有感.txt');

// 3.写入内容
writeStream.write('半亩方塘一鉴开\r\n')
writeStream.write('天光云影共徘徊\r\n')
writeStream.write('问渠那得清如许\r\n')
writeStream.write('为有源头活水来\r\n')

// 4.关闭通道 不是必须
// writeStream.close();

程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数。

流式写入方式适用于大文件写入或者频繁写入的场景, writeFile 适合于写入频率较低的场景。

2.2 文件读取

文件读取顾名思义,就是通过程序从文件中取出其中的数据,有如下几种 API:
方法说明readFile异步读取readFileSync同步读取createReadStream流式读取

2.2.1 异步读取

语法: fs.readFile(path, [options], callback)

参数说明:

  • path:文件路径
  • options:选项配置
  • callback:回调函数

返回值: undefined

代码示例:

// 1.引入 fs 模块
const fs = require('fs')

// 2.异步读取
fs.readFile('./座右铭.txt', (error, data) => {
    if (error) {
        console.log('文件读取错误')
        return
    }
    console.log(data.toString())
})

2.2.2 同步读取

语法: fs.readFileSync(path, [options])

参数说明:

  • path:文件路径
  • options:选项配置

返回值: string | Buffer

代码示例:

// 1.引入 fs 模块
const fs = require('fs')

// 2.同步读取
let data = fs.readFileSync('./座右铭.txt');
console.log(data.toString())

2.2.3 流式读取

语法: fs.createReadStream(path, [options])

参数说明:

  • path:文件路径
  • options:选项配置(可选)

返回值:Object

代码示例:

// 1.导入 fs 模块
const fs = require('fs')

// 2.创建读取流对象
const rs = fs.createReadStream('./观书有感.txt');

// 3.绑定 data 事件
rs.on('data', chunk => {
    // chunk:块儿、大块儿
    console.log(chunk)
    console.log(chunk.length)
    console.log(chunk.toString())
})

// 4.结束事件(可选)
rs.on('end', () => {
    console.log('文件读取完成')
})

2.3 文件移动与重命名

在 Node.js 中,可以使用 rename 或 renameSync 来移动或重命名文件或文件夹

语法:

  • fs.rename(oldPath, newPath, callback)
  • fs.renameSync(oldPath, newPath)

参数说明:

  • oldPath:文件当前的路径
  • newPath:文件新的路径
  • callback:操作后的回调

代码示例:

// 1.导入 fs 模块
const fs = require('fs');

// 2.文件重命名
// fs.rename('./座右铭-2.txt', './西汉名将.txt', error => {
//     if (error) {
//         console.log('文件重命名失败')
//            return ;
//     }
//     console.log('文件重命名成功')
// })

// 3.文件移动
// 文件夹如果不存在,会报错误 Error: ENOENT: no such file or directory
fs.rename('./西汉名将.txt', './文件/西汉名将.txt', error => {
    if (error) {
        console.log(error, '移动文件出错');
        return ;
    }
    console.log('操作成功')
})

2.4 文件删除

在 Node.js 中,可以使用 unlink 或 unlinkSync 或 rm 或 rmSync 来删除文件

语法:

  • fs.unlink(path, callback)
  • fs.unlinkSync(path)

参数说明:

  • path:文件路径
  • callback:操作后的回调

代码示例:

// 1.引入 fs 模块
const fs = require('fs')

// 2.调用 unlink 方法 
// unlinkSync:同步删除
// fs.unlink('./座右铭-3.txt', error => {
//     if (error) {
//         console.log('删除文件错误', error)
//         return;
//     }
//     console.log('删除文件成功')
// })

// 3.调用 rm 方法
// rmSync:同步删除
fs.rm('./文件/西汉名将.txt', error => {
    if (error) {
        console.log('文件删除失败', error)
        return;
    }
    console.log('文件删除成功')
})

2.5 文件夹操作

在 Node.js 中可以通过如下 API 对文件夹进行创建、读取、删除等操作
方法说明mkdir / mkdirSync创建文件夹readdir / readdirSync读取文件夹rmdir / rmdirSync删除文件夹

2.5.1 创建文件夹

在 Node.js 中,可以使用 mkdir 或 mkdirSync 来创建文件夹

语法:

  • fs.mkdir(path, [options], callback)
  • fs.mkdirSync(path, [options])

参数说明:

  • path:文件夹路径
  • options:选项配置(可选)
  • callback:操作后的回调

示例代码:

// 1.引入 fs 模块
const fs = require('fs')

// 2.创建文件夹
// mkdir make:制作 directory:目录 
fs.mkdir('./html', error => {
    if (error) {
        console.log('创建目录失败', error)
        return;
    }
    console.log('创建目录成功')
})

// 3.递归创建文件夹
fs.mkdir('./a/b/c', {
    recursive: true
}, error => {
    if (error) {
        console.log("递归创建文件夹失败", error)
        return;
    }
    console.log('递归创建文件夹成功')
})

// 4.递归同步创建文件夹
fs.mkdirSync('./a/b/c', {recursive: true});

2.5.2 读取文件夹

在 Node.js 中,可以使用 readdir 或 readdirSync 来读取文件夹

语法:

  • fs.readdir(path, [options], callback)
  • fs.readdirSync(path, [options])

参数说明:

  • path:文件夹路径
  • options:选项配置(可选)
  • callback:操作后的回调

示例代码:

// 1.引入 fs 模块
const fs = require('fs')

// 2.读取文件夹
// readdir read:读取 dir:directory 目录
fs.readdir('./', (error, data) => {
    if (error) {
        console.log('读取文件夹错误', error)
        return;
    }
    // [
    //     '1-文件写入.js',
    //     '2-追加写入.js',
    //     '3-流式写入.js',
    //     '4-文件读取.js',
    //     '5-流式读取.js',
    //     '6-练习-文件复制.js',
    //     '7-文件重命名与移动.js',
    //     '8-删除文件.js',
    //     '9-文件夹操作.js',
    //     'a',
    //     'html',
    //     '座右铭.txt',
    //     '文件',
    //     '观书有感.txt'
    // ]
    console.log(data)
})

//同步读取
// let data = fs.readdirSync('./');
// console.log(data);

2.5.3 删除文件夹

在 Node.js 中,可以使用 rmdir 或 rmdirSync 来删除文件夹

语法:

  • fs.rmdir(path, [options], callback)
  • fs.rmdirSync(path, [options]) 参数说明:
  • path:文件夹路径
  • options:选项配置(可选)
  • callback:操作后的回调

示例代码:

// 1.引入 fs 模块
const fs = require('fs')

// 2.删除文件夹
// fs.rmdir('./文件', error => {
//     if (error) {
//         console.log('删除文件夹失败', error)
//         return;
//     }
//     console.log('删除文件夹成功')
// })

// 3.递归删除文件夹 
// 递归删除文件夹失败 [Error: ENOTEMPTY: directory not empty, rmdir 'E:\JavaEE\frontend\nodejs-study\2-fs文件系统\a'] 

// 不推荐使用
// fs.rmdir('./a', {recursive: true}, error => {
//     if (error) {
//         console.log('递归删除文件夹失败', error)
//         return ;
//     }
//     console.log('递归删除文件夹成功')
// })

// 推荐使用
fs.rm('./a', {recursive: true}, error => {
    if (error) {
        console.log('递归删除文件失败', error)
        return;
    }
    console.log('递归删除文件成功')
})

//同步递归删除文件夹
fs.rmdirSync('./a', {recursive: true})

2.6 查看资源状态

在 Node.js 中,可以使用 stat 或 statSync 来查看资源的详细信息

语法:

  • fs.stat(path, [options], callback)
  • fs.statSync(path, [options])

参数说明:

  • path:文件夹路径
  • options:选项配置(可选)
  • callback:操作后的回调

示例代码:

// 1.引入 fs 模块
const fs = require('fs')

// 2.stat 方法 status 的缩写:状态
fs.stat('./观书有感.txt', (error, data) => {
    if (error) {
        console.log('操作失败', error)
        return;
    }
    // Stats {
    //     dev: 985301708,
    //     mode: 33206,
    //     nlink: 1,
    //     uid: 0,
    //     gid: 0,
    //     rdev: 0,
    //     blksize: 4096,
    //     ino: 281474979770305,
    //     size: 92,
    //     blocks: 0,
    //     atimeMs: 1684373309132.9426,
    //     mtimeMs: 1684289136772.1648,
    //     ctimeMs: 1684289136772.1648,
    //     birthtimeMs: 1684289136770.7136,
    //     atime: 2023 - 05 - 18 T01: 28: 29.133 Z,
    //     mtime: 2023 - 05 - 17 T02: 05: 36.772 Z,
    //     ctime: 2023 - 05 - 17 T02: 05: 36.772 Z,
    //     birthtime: 2023 - 05 - 17 T02: 05: 36.771 Z
    // }
    console.log(data)
    console.log(data.isFile())
    console.log(data.isDirectory())
})

// 3.同步获取状态
let data = fs.statSync('./观书有感.txt');
console.log(data)
console.log(data.isFile())
console.log(data.isDirectory())

结果值对象结构:

  • size:文件体积
  • birthtime:创建时间
  • mtime:最后修改时间
  • isFile:检测是否为文件
  • isDirectory:检测是否为文件夹

2.7 相对路径问题

fs 模块对资源进行操作时,路径的写法有两种:

  • 相对路径 ./座右铭.txt:当前目录下的座右铭.txt 座右铭.txt:等效于上面的写法 ../座右铭.txt:当前目录的上一级目录中的座右铭.txt
  • 绝对路径 D:/Program Files:windows 系统下的绝对路径 /usr/bin:Linux 系统下的绝对路径

相对路径中所谓的当前目录,指的是命令行的工作目录,而并非是文件的所在目录。所以当命令行的工作目录与文件所在目录不一致时,会出现一些 BUG。

2.8 __dirname

__dirname 与 require 类似,都是 Node.js 环境中的 '全局' 变量 __dirname 保存着当前文件所在目录的绝对路径,可以使用 __dirname 与文件名拼接成绝对路径

代码示例:

let data = fs.readFileSync(__dirname + '/data.txt');
console.log(data);

使用 fs 模块的时候,尽量使用 __dirname 将路径转化为绝对路径,这样可以避免相对路径产生的 Bug

2.9 练习

实现文件复制的功能

代码示例:

/**
 * 需求:
 *  复制【座右铭.txt】
 */

// 1.引入 fs 模块
const fs = require('fs');
// 全局对象,即 global 对象的属性,无须声明即可访问。它用于描述当前 Node 进程状态的对象,提供了一个与操作系统的简单接口。
const process = require('process')

// 方式一:使用 readFile
// 2.读取文件
// let data = fs.readFileSync('./座右铭.txt');

// // 3.写入文件
// fs.writeFileSync('./座右铭-2.txt', data);

// // 查看系统耗费内存
// // rss: 19795968 字节
// console.log(process.memoryUsage())

// 方式二:使用流式操作
// 2.创建流式读取
let rs = fs.createReadStream('./座右铭.txt');

// 3.创建流式写入
let ws = fs.createWriteStream('./座右铭-3.txt');

// // 4.绑定 data 事件
// rs.on('data', chunk => {
//     ws.write(chunk);
// })

// // 5.绑定 end 事件
// rs.on('end', () => {
//     // rss: 20885504 字节 相比于同步的方式占用内存会比较小
//     console.log(process.memoryUsage())
// })

// 4.使用 pipe(管道) 可直接复制
rs.pipe(ws)

3. path 模块

path 模块提供了操作路径的功能&#

标签: node.js

本文转载自: https://blog.csdn.net/liubenzun/article/details/137684773
版权归原作者 刘大本尊 所有, 如有侵权,请联系我们删除。

“Node.js超详细教程!”的评论:

还没有评论