官方文档:http://nodejs.cn/api/
常用API:path、Buffer、events、fs
一.path路径
const {path} = require(‘path’);
- path.normalize(path);//规范化指定的 path,并处理 ‘..’ 和 ‘.’ 片段
1 | path.normalize('C:\\temp\\\\foo\\bar\\..\\'); |
2 | // 返回: 'C:\\temp\\foo\\' |
- path.join([…paths]);//使用平台特定的分隔符把所有path片段连接到一起,并规范化生成的路径
1 | path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); |
2 | // 返回: '/foo/bar/baz/asdf' |
- path.resolve([…paths]);//将路径或路径片段的序列处理成绝对路径
1 | path.resolve('/foo/bar', './baz'); |
2 | // 返回: '/foo/bar/baz' |
- path.basename(path[, ext]);//返回path的最后一部分,类似于 Unix 中的basename命令
1 | path.basename('/foo/bar/baz/asdf/quux.html'); |
2 | // 返回: 'quux.html' |
- path.extname(path);//返回path的扩展名,即从path的最后一部分中的最后一个 .(句号)字符到字符串结束
1 | path.extname('index.html'); |
2 | // 返回: '.html' |
3 | path.extname('index.coffee.md'); |
4 | // 返回: '.md' |
- path.dirname(path);//返回path的目录名,类似于 Unix 中的dirname命令
1 | path.dirname('/foo/bar/baz/asdf/quux'); |
2 | // 返回: '/foo/bar/baz/asdf' |
- path.sep;//返回平台特定的路径片段分隔符
1 | 'foo\\bar\\baz'.split(path.sep); |
2 | // 返回: ['foo', 'bar', 'baz'] |
- path.delimiter;//返回平台特定的路径分隔符
1 | console.log(process.env.PATH); |
2 | // 输出: 'C:\Windows\system32;C:\Windows;C:\Program Files\node\' |
3 | process.env.PATH.split(path.delimiter); |
4 | // 返回: ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\'] |
path.win32;//返回为 Windows 实现的path方法
path.posix;//返回为 POSIX 实现的path方法
区别:
- __dirname、__filename总返回文件的绝对路径,前者到文件夹,后者到文件夹内文件
- process.cwd( )返回执行node命令所在文件夹
- ./或者../
- 在require方法中总是相对当前文件所在文件夹
- 在其他地方和process.cwd( )一样,相对node启动文件
二.Buffer缓冲
- 用于处理二进制数据流
- 实例类似整数数组,大小固定
- c++代码在V8堆外分配物理内存
①初始化
- Buffer.alloc(size[, fill[, encoding]]);//创建一个大小为size字节的Buffer
1 | const buf = Buffer.alloc(5, 'a'); |
2 | console.log(buf); |
3 | // 输出: <Buffer 61 61 61 61 61> |
- Buffer.allocUnsafe(size);//创建一个大小为size字节的Buffer,Buffer的内容是未知的
1 | const buf = Buffer.allocUnsafe(10); |
2 | console.log(buf); |
3 | // 输出: <Buffer a0 8b 28 3f 01 00 00 00 50 32> |
4 | // (输出的内容是内存的旧数据,每次都不同) |
- Buffer.from(array);//使用字节数组array创建Buffer
1 | // 创建一个包含字符串 'buffer' 的 UTF-8 字节的 Buffer。 |
2 | const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); |
- Buffer.from(string[, encoding]);//创建一个包含string的Buffer
1 | const buf1 = Buffer.from('this is a tést'); |
2 | const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); |
3 | console.log(buf1.toString()); |
4 | // 输出: this is a tést |
5 | console.log(buf2.toString()); |
6 | // 输出: this is a tést |
7 | console.log(buf1.toString('ascii')); |
8 | // 输出: this is a tC)st |
②类
- Buffer.byteLength(string[, encoding]);//返回字符串的实际字节长度
1 | const str = '\u00bd + \u00bc = \u00be'; |
2 | console.log(`${str}: ${str.length} 个字符,` +`${Buffer.byteLength(str, 'utf8')} 个字节`); |
3 | // 输出: ½ + ¼ = ¾: 9 个字符, 12 个字节 |
- Buffer.concat(list[, totalLength]);//返回一个合并了list中所有Buffer的新Buffer
1 | // 用含有三个 `Buffer` 的数组创建一个单一的 `Buffer`。 |
2 | const buf1 = Buffer.alloc(10); |
3 | const buf2 = Buffer.alloc(14); |
4 | const totalLength = buf1.length + buf2.length; |
5 | console.log(totalLength); |
6 | // 输出: 24 |
7 | const bufA = Buffer.concat([buf1, buf2], totalLength); |
8 | console.log(bufA); |
9 | // 输出: <Buffer 00 00 00 00 ...> |
10 | console.log(bufA.length); |
11 | // 输出: 24 |
- Buffer.isBuffer(obj);//如果obj是一个Buffer,则返回true,否则返回false
③实例
const buf = Buffer.from(‘This is a test!’);
- buf.length;//回内存中分配给buf的字节数
1 | const buf = Buffer.alloc(1234); |
2 | console.log(buf.length); |
3 | // 输出: 1234 |
- buf.toString([encoding[, start[, end]]]);//根据encoding指定的字符编码将buf解码成字符串
1 | const buf = Buffer.from('tést'); |
2 | console.log(buf.toString('hex')); |
3 | // 输出: 74c3a97374 |
4 | console.log(buf.toString('utf8', 0, 3)); |
5 | // 输出: té |
- buf.fill(value[, offset[, end]][, encoding]);//用指定的value填充buf
1 | // 用 ASCII 字符 'h' 填充 `Buffer`。 |
2 | const b = Buffer.allocUnsafe(50).fill('h'); |
3 | console.log(b.toString()); |
4 | // 输出: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh |
- buf.equals(otherBuffer);//如果buf与otherBuffer具有完全相同的字节,则返回true,否则返回 false
1 | const buf1 = Buffer.from('ABC'); |
2 | const buf2 = Buffer.from('414243', 'hex'); |
3 | const buf3 = Buffer.from('ABCD'); |
4 | console.log(buf1.equals(buf2)); |
5 | // 输出: true |
6 | console.log(buf1.equals(buf3)); |
7 | // 输出: false |
- buf.indexOf(value[, byteOffset][, encoding]);//返回buf中首次出现value的索引,如果buf没包含value则返回-1
1 | const buf = Buffer.from('this is a buffer'); |
2 | console.log(buf.indexOf('this')); |
3 | // 输出: 0 |
4 | console.log(buf.indexOf('is')); |
5 | // 输出: 2 |
- buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]]);//拷贝buf中某个区域的数据到target中的某个区域,即使target的内存区域与buf的重叠
1 | // 创建两个 `Buffer`。 |
2 | const buf1 = Buffer.allocUnsafe(26); |
3 | const buf2 = Buffer.allocUnsafe(26).fill('!'); |
4 | for (let i = 0; i < 26; i++) { |
5 | // 97 是 'a' 的十进制 ASCII 值。 |
6 | buf1[i] = i + 97; |
7 | } |
8 | // 拷贝 `buf1` 中第 16 至 19 字节偏移量的数据到 `buf2` 第 8 字节偏移量开始。 |
9 | buf1.copy(buf2, 8, 16, 20); |
10 | console.log(buf2.toString('ascii', 0, 25)); |
11 | // 输出: !!!!!!!!qrst!!!!!!!!!!!!! |
④字符串解码器
string_decoder模块提供了一个 API,用于把Buffer对象解码成字符串
1 | const { StringDecoder } = require('string_decoder'); |
2 | const decoder = new StringDecoder('utf8'); |
3 | const cent = Buffer.from([0xC2, 0xA2]); |
4 | console.log(decoder.write(cent)); |
三.events事件
const EventEmitter = require(‘events’);//所有能触发时间的对象都是EventEmitter类的实例
- emitter.on(eventName, listener);//添加listener函数到名为eventName的事件的监听器数组的末尾,注册监听器
1 | const myEE = new EventEmitter(); |
2 | myEE.on('foo', () => console.log('a')); |
3 | myEE.prependListener('foo', () => console.log('b')); |
4 | myEE.emit('foo'); |
5 | // b |
6 | // a |
- emitter.emit(eventName[, …args]);//按照监听器注册的顺序,同步地调用每个注册到名为 eventName的事件的监听器,并传入提供的参数,触发事件
- emitter.once(eventName, listener);//添加单次监听器listener到名为eventName的事件
- emitter.removeListener(eventName, listener);//从名为eventName的事件的监听器数组中移除指定的listener
- emitter.removeAllListeners([eventName]);//移除全部监听器或指定的eventName事件的监听器
四.fs文件系统
const fs = require(‘fs’);
①读
- fs.readFile(path[, options], callback);//异步地读取文件的内容
1
fs.readFile('/etc/passwd', 'utf8', callback);
2
fs.readFile('/etc/passwd', (err, data) => {
3
if (err) throw err;
4
console.log(data);
5
});
- fs.readFileSync(path[, options]);//同步返回文件的内容,同步比异步快,但是会阻塞
②写
- fs.writeFile(file, data[, options], callback);//异步地将数据写入文件,如果文件已存在,则覆盖文件
1
fs.writeFile('文件.txt', '内容', 'utf8', callback);
2
const data = new Uint8Array(Buffer.from('Node.js中文网'));
3
fs.writeFile('文件.txt', data, (err) => {
4
if (err) throw err;
5
console.log('文件已保存');
6
});
③状态
- fs.stat(path[, options], callback);//异步查看文件的属性
1
fs.stat('文件路径', (err, stats) => {
2
if (err) throw err;
3
console.log(stats.isFile( ));//文件
4
console.log(stats.isDirectory( ));//文件夹
5
console.log(stats);//状态
6
});
④重命名
- fs.rename(oldPath, newPath, callback);//异步地把文件oldPath重命名为newPath
1
fs.rename('旧文件.txt', '新文件.txt', (err) => {
2
if (err) throw err;
3
console.log('已完成重命名');
4
});
⑤删除
- fs.unlink(path, callback);//异步地移除一个文件或符号链接
1
// 假设 'path/file.txt' 是一个普通文件。
2
fs.unlink('path/file.txt', (err) => {
3
if (err) throw err;
4
console.log('文件已删除');
5
});
- fs.readdir(path[, options], callback);//异步读取目录(文件夹)的内容
- fs.mkdir(path[, options], callback);//异步地创建目录
1
// 创建 /tmp/a/apple 目录,不管 `/tmp` 和 /tmp/a 目录是否存在。
2
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
3
if (err) throw err;
4
});
- fs.rmdir(path, callback);//异步地删除目录
- fs.watch(filename[, options][, listener]);//监视filename的变化,filename可以是一个文件或一个目录
⑥流
有向传输数据
const rs = fs.creatReadStream(‘路径’);
- rs.pipe(process.stout);
const ws = fs.creatWriteStream(‘路径’);
- ws.write(‘字符串’);
- ws.end( );
⑦解决回调地狱
异步回调里有回调,回调里又有回调
1 | const util = require('util'); |
2 | const fs = require('fs'); |
3 | |
4 | const stat = util.promisify(fs.stat); |
5 | stat('.').then((stats) => { |
6 | // Do something with `stats` |
7 | }).catch((error) => { |
8 | // Handle the error. |
9 | }); |
1 | const util = require('util'); |
2 | const fs = require('fs'); |
3 | |
4 | const stat = util.promisify(fs.stat); |
5 | |
6 | async function callStat() { |
7 | const stats = await stat('.'); |
8 | console.log(`This directory is owned by ${stats.uid}`); |
9 | } |