Note.js 笔记

一、Buffer(缓冲区)

在 JavaScript 中,字符串是以 UTF-16 编码存储的,而不是字节流(如 ASCII 或 UTF-8)。对于需要处理二进制数据的操作(比如读取文件、从网络接收数据等),JavaScript 原生并没有内建的数据结构来直接处理这些原始数据。Buffer 就是为了解决这个问题而诞生的,它允许在内存中操作原始的二进制数据。

1.1、特点

原始二进制数据存储:Buffer 不是以字符的形式存储数据,而是直接以字节的形式存储数据。

固定大小:一旦创建,Buffer 的大小是固定的,不能动态增大或缩小。

直接访问内存:Buffer 提供了直接访问内存的能力,因此操作效率高。

1.2、创建Buffer

Buffer.from():从现有的字符串、数组或其他 Buffer 创建一个新的 Buffer。

const buf1 = Buffer.from('hello', 'utf-8'); // 创建一个包含字符串 "hello" 的 Buffer,<Buffer 68 65 6c 6c 6f>
const buf2 = Buffer.from([1, 2, 3, 4]);    // 从数组创建 Buffer,<Buffer 01 02 03 04>

Buffer.alloc():分配一个指定大小的 Buffer,并填充为零。

const buf = Buffer.alloc(10);  // 创建一个大小为 10 字节的 Buffer,初始化为零

Buffer.allocUnsafe():分配一个指定大小的 Buffer,但不初始化。该方法返回一个未初始化的 Buffer,操作速度更快,但需要==小心使用==,因为它可能包含之前的内存数据。

const buf = Buffer.allocUnsafe(10);  // 创建一个大小为 10 字节的未初始化 Buffer

1.3、常见的 Buffer 方法

buf.toString([encoding], [start], [end]):将 Buffer 转换为字符串。可以指定编码格式(如 'utf-8'、'ascii'、'hex' 等)。

const buf = Buffer.from('hello');
console.log(buf.toString()); // 输出 'hello'
console.log(buf.toString('hex')); // 输出 '68656c6c6f'

buf.length:返回 Buffer 的字节长度。

const buf = Buffer.from('hello');
console.log(buf.length); // 输出 5

buf.write(string, [offset], [length], [encoding]):将字符串写入 Buffer 中,从指定的偏移位置开始,支持指定编码格式。

const buf = Buffer.alloc(10);
buf.write('hello');
console.log(buf); // 输出 <Buffer 68 65 6c 6c 6f 00 00 00 00 00>

buf.slice([start], [end]):从 Buffer 中截取指定范围的子 Buffer。

const buf = Buffer.from('hello');
const subBuf = buf.slice(1, 4);
console.log(subBuf.toString()); // 输出 'ell'

1.4、Buffer 与字符串的转换

Buffer 可以与字符串进行互相转换,支持多种编码格式。最常用的编码格式是 utf-8、ascii 和 hex。

从 Buffer 转换为字符串

const buf = Buffer.from('hello', 'utf-8');
console.log(buf.toString('utf-8')); // 输出 'hello'

从字符串转换为 Buffer

const buf = Buffer.from('hello', 'utf-8');
console.log(buf); // 输出 <Buffer 68 65 6c 6c 6f>

用途

处理文件 I/O:在 Node.js 中,文件读取和写入通常涉及二进制数据。Buffer 使得可以高效地读取和写入原始数据(如图片、音频、视频等)。

网络通信:许多网络协议(如 HTTP)使用二进制数据流。Buffer 允许 Node.js 高效地处理这些数据。

加密:加密算法通常需要处理二进制数据,Buffer 提供了适合加密操作的数据格式。

流处理:处理大量数据时,Buffer 在流(Stream)操作中扮演着重要角色,因为它可以在内存中以字节流的形式传输数据。

二、fs模块

fs(File System)模块是一个内置模块,用于与文件系统进行交互。它允许你在服务器端执行文件的读、写、删除、重命名等操作。fs 模块提供了同步和异步的 API,可以用来处理文件和目录。

在开始之前请先导入 fs 模块:const fs = require('fs');

2.1、写入文件

异步写:

fs.writeFile('./fileName.txt','hello world',(err)=>{
    if(err){ console.log(err); return; }
    console.log('文件写入成功!!');
})

同步写:

fs.writeFileSync('./fileName.txt','hello world!!');

2.2、读取文件

异步读:

fs.readFile('./fileName.txt', 'utf8', (err,data) => {
    if (err) { console.log(err); return; }
    console.log(data);
})

同步读:

const data = fs.readFileSync('./fileName.txt', 'utf8');
console.log(data);

2.3、追加字符

异步写:

fs.appendFile('./fileName.txt','\nhello java!','utf8',(err)=>{
    if(err){ console.log(err); return; }
    console.log('追加成功!');
})

同步写:

fs.appendFileSync('./fileName.txt','\nHello Python!','utf8');

2.4、删除文件

异步删:

fs.unlink('./fileName.txt',(err) => {
    if(err){ console.log(err); return}
    console.log('文件删除成功!');
})

同步删:

fs.unlinkSync('./fileName.txt');

2.5、重命名文件

异步重命名:

fs.rename('./fileName.txt', './fileNameNEW.txt',(err)=>{
    if(err){ console.log(err); return; }
    console.log('重命名成功!');
})

同步重命名:

fs.renameSync('./fileNameNEW.txt','./fileName.txt');

2.6、检查文件/目录是否存在

异步检查:

fs.access('./fileName.txt', fs.constants.F_OK, (err) => {
    if (err) {
        console.log('文件或目录不存在!');
    } else {
        console.log('文件或目录存在!');
    }
});

同步检查01:

try {
    fs.accessSync('./fileName.txt')
    console.log('文件或目录存在!');
} catch (err) {
    console.log('文件或目录不存在!');
}

同步检查02:

if(fs.existsSync('./fileName.txt')){
    console.log('文件或目录存在!');
}else {
    console.log('文件或目录不存在!');
}

2.7、创建目录

异步创建:

fs.mkdir('./新目录/a/b',{recursive:true},(err)=>{
    if (err) throw err;
    console.log('创建成功!');
})

同步创建:

fs.mkdirSync('./新目录/c/s',{recursive:true});

2.8、删除目录

异步删除:

// 旧版使用 rmdir
fs.rm('./新目录',{recursive:true},(err) => { 
    if (err) throw err;
    console.log('删除成功!');
})

同步删除:

fs.rmSync('./新目录',{recursive:true});

2.9、读取目录内容

异步读目录:

fs.readdir('./新目录', (err, data) => {
    if (err) throw err;
    console.log(data);
})

同步读目录:

const dir =  fs.readdirSync('../');
console.log(dir);

2.10、文件状态信息

异步:

fs.stat('./sss', (err, stats) => {
    if (err) {
        console.error('Error:', err);
    } else {
        console.log(stats.isDirectory()); // true: 如果路径是目录
        console.log(stats.isFile()); // true: 如果路径是文件
    }
});

同步:

try {
    const dir = fs.statSync('./新目录');
    console.log(dir.isDirectory()); // true: 如果路径是目录
    console.log(dir.isFile()); // false: 如果路径是文件
}catch (err) {
    console.error('Error:', err);
}

三、使用流(Stream)

3.1、Readable Stream(可读流)

导包:

const fs = require('fs');

创建一个可读流

const rs = fs.createReadStream('./abc.txt', { encoding: 'utf8' });

监听 'data' 事件,逐块读取文件内容

rs.on('data',(chunk) => {
    console.log('chunk:', chunk);
})

监听 'end' 事件,文件读取完毕

rs.on('end', () => {
    console.log('文件读取完毕');
});

fs.createReadStream(path):用于创建可读流。

data 事件:每次读取到数据块时触发。

end 事件:数据读取完成时触发。

3.2、Writable Stream(可写流)

Writable 流用于向文件或网络发送数据。

导包:

const fs = require('fs');

创建一个可写流:

const ws = fs.createWriteStream('output.txt', { encoding: 'utf8' });

使用 write() 方法写入数据:

ws.write('Hello, world!\n');
ws.write('This is a test.\n');

结束写入:

ws.end(() => {
  console.log('数据写入完毕');
});

3.3、Duplex Stream(双工流)

导包:

const fs = require('fs');
const net = require('net');

创建一个 TCP 客户端(即双工流)

const client = net.createConnection({ port: 8080 }, () => {
    console.log('连接到服务器');
    client.write('Hello, Server!');
});

client.on('data', (data) => {
    console.log('收到来自服务器的数据:', data.toString());
    client.end();  // 结束连接
});

client.on('end', () => {
    console.log('连接关闭');
});

三、HTTP 模块

最后修改:2025 年 01 月 27 日
咱们谁跟谁,用不着~