Skip to content

fs

1 读取整个文件

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

// 1 读取文件不存在会报错
// 2 写入文件的时候,文件不存在,会创建这个文件,如果文件中有内容会清空文件内密
fs.readFile(path.resolve(__dirname, "index.md"), function (err, data) {
  if (err) {
    return console.log(err);
  }
  // 这种模式如果文件内容 是非常的大,不能采用此操作,会淹没可用内存
  fs.writeFile(path.resolve(__dirname, "copy.txt"), data, function (err) {
    if (err) {
      return console.log(err);
    }
    console.log("写入成功");
  });
});

2 按需读取-流

  • flags: 表示打开文件要干什么?
  • r -> read 如果文件不存在会报错 fs.readFile
  • r+ -> 在读取的基础上能写入,如果文件不存在会报错
  • w -> 写入内容,如果文件不存在会创建,如果有内容会清空文件 fs.writeFie
  • w+ -> 在写入的基础上增加读取的功能,如果文件不存在会创建,如果有内容会清空文件
  • a -> 追加内容,如果文件不存在会创建,如果有内容会追加内容 fs.appendFile
js
const fs = require("fs");
const path = require("path");
// 读一部分写一部分,使用流处理
const buf = Buffer.alloc(3);

// flags: 表示打开文件要干什么?
// r -> read 如果文件不存在会报错  fs.readFile
// r+ -> 在读取的基础上能写入,如果文件不存在会报错
// w -> 写入内容,如果文件不存在会创建,如果有内容会清空文件  fs.writeFie
// w+ -> 在写入的基础上增加读取的功能,如果文件不存在会创建,如果有内容会清空文件
// a -> 追加内容,如果文件不存在会创建,如果有内容会追加内容  fs.appendFile
fs.open(path.resolve(__dirname, "index.md"), "r", function (err, fd) {
  // fd file-descriptor 表示我们当前操作的文件是name.txt 而且是要做读取操作,是number类型

  // 所谓的读取还是写入 是有参照物的
  // 将这个数据写入到buffer中,从buffer第0个位置写入写入3个
  fs.read(fd, buf, 0, 3, 0, function (err, bytesRead) {
    // bytesRead 真正的写入个数

    // mode   rwx    r-x          r-x
    //        用户  用户所在的组   其他人
    // 1 执行  2 写入  4读取
    // 755 chomd -R 777
    //  0o666 -> 438
    fs.open(path.resolve(__dirname, "copy.txt"), "w", 438, function (err, wfd) {
      // 写入这个buffer,从buffer的第0个位置开始写入,写入的个数
      fs.write(wfd, buf, 0, bytesRead, 0, function (err) {
        console.log("写入成功");
      });
    });
  });
});

3 批量读取

js
const fs = require("fs");
const path = require("path");
// 读一部分写一部分,使用流处理
const buf = Buffer.alloc(3);

// 按需的优化代码
fs.open(path.resolve(__dirname, "index.md"), "r", function (err, fd) {
  fs.open(path.resolve(__dirname, "copy.txt"), "w", 438, function (err, wfd) {
    let readOffset = 0;
    let writeOffset = 0;
    ~(function next() {
      fs.read(fd, buf, 0, buf.length, readOffset, function (err, bytesRead) {
        readOffset += bytesRead;

        fs.write(wfd, buf, 0, bytesRead, writeOffset, function (err, written) {
          // 写入的个数
          writeOffset += written;
          if (bytesRead < buf.length) {
            // 每次判断一下读取的个数 是否小于 buffer的长度
            return console.log("拷贝完毕");
          }
          next();
        });
      });
    })();
  });
});
  • Buffer 用于 node 处理二进制数据的,前端没有所谓的二进制格式的数据,只有字符,而且前端的 blob 对象不能修改

  • node 就自己发明了一个 buffer(用于存储二进制格式的类型)

  • 二进制比较长 buffer 的展现形式是 16 进制的

  • 进制之间是有转化 2,8,16(本身是不会变的)

  • 二进制,一个字节是由 8 个位 bit 组成 1,0

  • 0o 开头是 8 进制

  • 0b 开头是 2 进制

  • 0x 开头是 16 进制

js
// 二进制转10进制
console.log(parseInt("1010", 2));

// 任意进制转任意进制
console.log((0b1010).toString(10));

2 一道题

0.1 + 0.2 != 0.3

小数转化二进制后精度会出现无限循环,导致最终结果大于 0.3

js
210 乘权求和
10 》 其他  反向取余
小数 》 二进制  乘二取整法

0.1 * 2 = 0.2 -> 0
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 0.6 -> 1
0.6 * 2 = 0.2 -> 1

3 base64 编码

  • base64 组成:英文26个小写,26个大写,0-9的10个数字,+/ 一共 64 个
  • node 中一个汉字三个字节
js
console.log(Buffer.from("帅")); // 0xe5 0xb8 0x85

// 变成二进制 在拆分成 一个个的 字节不大于64的 去取对应的编码
console.log((0xe5).toString(2)); // 11100101
console.log((0xb8).toString(2)); // 10111000
console.log((0x85).toString(2)); // 10000101

// 三个字节-每个8位
// 255        255         255
// 11100101   10111000    10000101

// 拆分为6位,用四个字节表示,不够补0
// 111001    011011    100010     000101
// 00111001  00011011  00100010   00000101

console.log((0b00111001).toString()); // 57
console.log((0b00011011).toString()); // 27
console.log((0b00100010).toString()); // 34
console.log((0b00000101).toString()); // 5

// 57  27  34  5
let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
str += str.toLowerCase();
str += "0123456789";
str += "+/";
console.log(str[57] + str[27] + str[34] + str[5]);
// 5bif  > base64编码

// 一个汉字是3个字节 转换成base64之后会比之前大1/3。
// 如果是比较大的内容 不适合base64编码

4 声明方式

js
// buffer 的声明方式 (声明内存的,声明出来的结果是引用类型的)
// 大小代表的是内存大小,再声明的过程中需要给定长度

// node中操作文件的单位是字节,不是位
console.log(Buffer.alloc(3));
// 将内容直接转化为二进制存放
console.log(Buffer.from("中文"));
// toString方法 将二进制转化为其他格式
console.log(Buffer.from("中文").toString());

5 拼接

js
// Buffer拼接:声明一个更到的
let b1 = Buffer.from("你好");
let b2 = Buffer.from("世界");

let b3 = Buffer.alloc(12);
b1.copy(b3, 0, 0, 6);
b2.copy(b3, 6, 0, 6);
console.log(b3.toString());

// 自定义
Buffer.prototype.copy = function (
  target,
  targetStart,
  sourceStart = 0,
  sourceEnd = this.length
) {
  for (let i = 0; i < sourceEnd - sourceStart; i++) {
    target[targetStart + i] = this[sourceStart + i];
  }
};

Buffer.prototype.contact = function (
  list,
  len = list.reduce((memo, current) => (memo += current.length), 0)
) {
  const buf = Buffer.alloc(len);
  let offset = 0;
  list.forEach((element) => {
    b.copy(buf, offset);
    offset += b.length;
  });
  return buf;
};
let b3 = Buffer.contact([b1, b2, b1]);
console.log(b3.toString());

常用方法

  • contact()
  • toString()
  • slice()
  • isBuffer()

Released under the MIT License.