likes
comments
collection
share

Node.js基础使用(Path,Buffer,fs)

作者站长头像
站长
· 阅读数 25

Path

const path = require('path')
console.log(__filename)
// 获取路径基础名称,最后一部分
/**
 * 返回的就是接收路径当中的最后一部分
 * 第二个参数表示扩展名,如果没有设置就返回完整文件名带后缀
 * 第二个参数作为后缀时,如果没有在当前路径中被匹配到,那么就会忽略
 * 处理目录路径的时候如果结尾处有路径分隔符,则也会被忽略掉
 */
console.log(path.basename(__filename))
console.log(path.basename(__filename,'.js')) // 第二个可选参数,匹配后缀,有就显示文件名称,没有就反正完整文件名
console.log(path.basename(__filename,'.css'))
console.log(path.basename('/a/b/c')) // 返回path路径最后一部分

// 获取路径目录名(路径)
/**
 * 返回路径中最后一个部分的上一层目录所在路径
 */
console.log(path.dirname(__filename))
console.log(path.dirname('/a/b/c')) // /a/b 
console.log(path.dirname('/a/b/c/')) // /a/b

// 获取路径扩展名
/**
 * 返回path路径中相应文件的后缀名
 * 如果path路径当中存在多个点,它匹配的是最后一个点到结尾的内容
 * 
 */
console.log(path.extname(__filename)) // .js
console.log(path.extname('/a/b')) // 空
console.log(path.extname('/a/b/index.html.js.css')) // .css
console.log(path.extname('/a/b/index.html.js.'))  // .

// 解析路径
/**
 * 接收一个路径,返回一个对象,包含不同的信息
 * root dir base ext name(最后一部分名称)
 */
const obj = path.parse('a/b/c/index.html')
// {
//     root: '',
//     dir: 'a/b/c',
//     base: 'index.html',
//     ext: '.html',
//     name: 'index'
// }
const obj1 = path.parse('a/b/c/') // { root: '', dir: 'a/b', base: 'c', ext: '', name: 'c' }
const obj2 = path.parse('a/b/c') // { root: '', dir: 'a/b', base: 'c', ext: '', name: 'c' }
const obj3 = path.parse('./a/b/c') // { root: '', dir: './a/b', base: 'c', ext: '', name: 'c' }

// 序列化路径
const obj4 = path.parse('./a/b/c')  
console.log(path.format(obj4)) // ./a/b\c

// 判断当前路径是否为绝对路径
console.log(path.isAbsolute('foo')) // false
console.log(path.isAbsolute('/foo')) // true
console.log(path.isAbsolute('///foo')) // true
console.log(path.isAbsolute('')) // false
console.log(path.isAbsolute('.')) // false
console.log(path.isAbsolute('../bar'))  // false

// 拼接路径
console.log(path.join('a/b','c','index.html')) // a\b\c\index.html
console.log(path.join('/a/b','c','index.html')) // \a\b\c\index.html
console.log(path.join('a/b','c','../','index.html')) // a\b\index.html
console.log(path.join('a/b','c','./','index.html')) // a\b\c\index.html
console.log(path.join('a/b','c','','index.html'))  // a\b\c\index.html
console.log(path.join('')) // .  当前工作目录

// 规范化路径
console.log(path.normalize('a/b/c/d')) // a\b\c\d
console.log(path.normalize('a///b/c../d'))  // a\b\c..\d
console.log(path.normalize('a//\\b/c\\/d'))  // a\b\c\d
console.log(path.normalize('a//\b/c\\/d'))  // a\c\d  反斜杠后字母具有特殊意义
console.log(path.normalize('')) // .

// 绝对路径
console.log(path.resolve()) // 打印当前目录
console.log(path.resolve('index.html')) // 打印当前目录/index.html 最常用写法
console.log(path.resolve('a','b'))  //  当前目录\a\b
/**
 * resolve([from],to) 把to部分拼接为绝对路径,如果拼接完并不是一个绝对路径,
 * 那就把当前工作目录加上,让他成为一个绝对路径。from
 */
console.log(path.resolve('/a','b'))  // D:\a\b  这里 '/a' 'b'成为了to
console.log(path.resolve('a','/b'))  // D:\b   这里a被忽略, '/b'成为了to
console.log(path.resolve('/a','/b'))  // D:\b  这里 '/a'被忽略  '/b'成为了to

Buffer

Buffer让Js可以操作二进制全局变量,无须require的一个全局变量实现nodejs平台下的二进制数据操作不占据V8堆内存大小的内存空间内存的使用由Node控制,由v8的GC回收一般配合Stream流使用个,充当数据缓冲区

alloc 创建指定字节大小的bufferallocUnsafe 创建指定大小的buffer(不安全)from 接收数据,创建buffer

const b1 = Buffer.alloc(10); // 单位是字节
console.log(b1); // <Buffer 00 00 00 00 00 00 00 00 00 00>
const b2 = Buffer.allocUnsafe(10);
console.log(b2); // <Buffer 00 00 00 00 00 00 00 00 00 00>
const b3 = Buffer.from("中");
console.log(b3); // <Buffer e4 b8 ad>  16进制  utf-8 一个汉字三个字节
const b4 = Buffer.from([1, 2, 3]);
console.log(b4); // <Buffer 01 02 03>
const b5 = Buffer.from([1, 2, "中"]);
console.log(b5); // <Buffer 01 02 00>
const b6 = Buffer.from([0xe4, 0xb8, 0xad]);
console.log(b6, b6.toString()); // <Buffer e4 b8 ad> 中

const a1 = Buffer.alloc(3);
const a2 = Buffer.from(a1); // 空间并非共享
console.log(a1, a2); // <Buffer 00 00 00> <Buffer 00 00 00>
a1[0] = 1;
console.log(a1, a2);  // <Buffer 01 00 00> <Buffer 00 00 00>

fill 使用数据填充bufferwrite 向buffer中写入数据toString 从buffer中提取数据slice 截取bufferindexOf 在buffer中查找数据copy 拷贝buffer中数据

let buf = Buffer.alloc(6);
buf.fill("123", 1, 3); // 第二个参数是填充开始下标位置,第三个代表结束位置,这个位置取不到
console.log(buf, buf.toString()); // <Buffer 31 32 33 31 32 33> 123123 ,长度不够就填充,超出就截取

buf.fill(123)
console.log(buf, buf.toString());  // <Buffer 7b 7b 7b 7b 7b 7b> {{{{{{  7b专uft-8编码是{

buf.write("123", 1, 4); // 第二个参数是开始位置,第三个参数为长度
console.log(buf, buf.toString()); // <Buffer 31 32 33 00 00 00> 123


buf = Buffer.from("默认值");
console.log(buf, buf.toString()); // <Buffer e9 bb 98 e8 ae a4 e5 80 bc> 默认值
console.log(buf, buf.toString("utf-8", 3, 9)); // <Buffer e9 bb 98 e8 ae a4 e5 80 bc> 认值 ,第二个参数表示开始下标,第三个表示结束位置


buf = Buffer.from("默认值");
let b1 = buf.slice();  // 第一第二个参数表示开始位置和结束位,顾头不顾尾 ,如果是负数,表示从尾部开始,-3打印出来“值”
console.log(b1, b1.toString()); // <Buffer e9 bb 98 e8 ae a4 e5 80 bc> 默认值   ---从头截取到尾部

buf = Buffer.from("默认值,阿西洛夫");
console.log(buf, buf.indexOf("阿")); // <Buffer e9 bb 98 e8 ae a4 e5 80 bc 2c e9 98 bf e8 a5 bf e6 b4 9b e5 a4 ab> 10 ----中文占三个字节,所以阿字下标是10
console.log(buf, buf.indexOf("啊", 4)); // <Buffer e9 bb 98 e8 ae a4 e5 80 bc 2c e9 98 bf e8 a5 bf e6 b4 9b e5 a4 ab> -1

let b1 = Buffer.alloc(6);
let b2 = Buffer.from("前端");
b2.copy(b1); // b2拷贝到b1里面
console.log(b1.toString(), b2.toString()); // 前端 前端

let b1 = Buffer.alloc(6);
let b2 = Buffer.from("前端");
b2.copy(b1); // b2拷贝到b1里面 ,第二个参数表示拷贝开始位置,第三个参数从源buffer读取开始位置,第四个参数表示源buffer读取结束位置,顾头不顾尾
console.log(b1.toString(), b2.toString()); // 前端 前端

let b1 = Buffer.from("前端");
let b2 = Buffer.from("性能");
let b = Buffer.concat([b1, b2]);
console.log(b, b.toString()); // <Buffer e5 89 8d e7 ab af e6 80 a7 e8 83 bd> 前端性能
let b3 = Buffer.concat([b1, b2], 9);
console.log(b3, b3.toString()); // <Buffer e5 89 8d e7 ab af e6 80 a7> 前端性

let b4 = Buffer.alloc(3);
console.log(Buffer.isBuffer(b4));  // true

对Buffer实现数组的split操作

// buffer长度创建后是固定的,实现一个split方法
ArrayBuffer.prototype.split = function (sep) {
  let len = Buffer.from(sep).length;
  let result = [];
  let start = 0;
  let offset = 0;

  while ((offset = this.indexOf(sep, start) !== -1)) {
    result.push(this.slice(start, offset));
    start = offset + len; // 更新start位置
  }
  result.push(this.slice(start))
  return result;
};

let buf = "小明喜欢吃馒头,吃水果,吃米饭吃";
let bufArr = buf.split("吃");
console.log(bufArr);  // [ '小明喜欢', '馒头,', '水果,', '米饭', '' ]

buffer应用场景图片base64编码转换

const fs = require('fs');
const path = require('path');
// function to encode file data to base64 encoded string
function base64_encode(file) {
 let bitmap = fs.readFileSync(file);
 return Buffer.from(bitmap).toString('base64');
}
// function to create file from base64 encoded string
function base64_decode(base64str, file) {
 let bitmap = Buffer.from(base64str, 'base64');
 fs.writeFileSync(file, bitmap);
}
let base64str = base64_encode(path.join(__dirname, './a.png'));
console.log(base64str);
base64_decode(base64str, path.join(__dirname, 'copyA.png'));

文件读取buffer有乱码的问题解决方案1

// 可读流有⼀个设置编码的⽅法setEncoding():
默认情况下没有设置字符编码,流数据返回的是 Buffer 对象。 如果设置了字符编码,则流数据返
回指定编码的字符串
// fs.createReadStream 的 options 中 highWaterMark默认是64k
const rs = fs.createReadStream(path.join(__dirname, '1.txt'),
let rs = fs.createReadStream('test.md', {highWaterMark: 11});
rs.setEncoding('utf8');

解决方案2

const res = fs.createReadStream(path.join(__dirname, '1.txt');
// 将⼩Buffer 拼接成⼤Buffer 对象
let chunks = [];
let size = 0;
res.on('data', function (chunk) {
 chunks.push(chunk);
 size += chunk.length;
});
res.on('end', function () {
 let buf = Buffer.concat(chunks, size);
 let str = iconv.decode(buf, 'utf8');  // 累加buffer,iconv
 console.log(str);
});

FS

Fs基本操作类Fs常用API常见flag操作符

r 可读  w 可写  s 同步  + 执行相反操作 x排它操作 a 追加操作

代码示例

const fs = require("fs");

// readFile
fs.readFile(path.resolve("file.txt"), "utf-8", (err, data) => {
  console.log(err); // null ,路径错误就会打印错误信息
  console.log(data); // 123
});

fs.writeFile("data.txt", "hello node.js", (err) => {
  if (!err) {
    fs.readFile("data.txt", "utf-8", (err, data) => {
      console.log(data);  // hello node.js
    });
  }
});

fs.writeFile("data.txt", "hello node.js", (err) => {  // writeFile覆盖写操作
  if (!err) {
    fs.readFile("data.txt", "utf-8", (err, data) => {
      console.log(data);  // hello node.js
    });
  }
});

fs.writeFile("data.txt", "abcd" ,{
    mode:438,
    flag:'r+', // 这个模式不会默认清空文件
    encoding:'utf-8'
}, (err) => {  // writeFile覆盖写操作
  if (!err) {
    fs.readFile("data.txt", "utf-8", (err, data) => {
      console.log(data);  // abcdo node.js
    });
  }
});

// 追加写入
fs.appendFile('data.txt','前端',(err)=>{
   console.log("write")
})

fs.copyFile('data.txt','dataCopy.txt',(err)=>{
    console.log("copy success")
})

fs.watchFile('data.txt',{interval:20},(cur,pre)=>{ // 每20毫秒监控一次
    if(cur.mtime !== pre.mtime){
        console.log("file modify") // 修改时会有打印
        fs.unwatchFile('data.txt') // 取消监控
    }
})