Skip to content

fs(file system)

文件操作的 API,有同步和异步。

阻塞的文件读写

阻塞的优点是速度快,可以马上拿到结果。缺点是后面的逻辑需要等待。

js
const fs = require('fs')
const path = require('path')

// 读取的数据默认的编码都是 null,即二进制数据(Buffer)。
// 如果文件不存在,报错。
const content = fs.readFileSync(path.resolve(__dirname, 'foo.md'))
// 写入操作也是二进制,不需要考虑编码问题。
// 如果文件不存在,会创建。如果文件存在,会覆盖。
fs.writeFileSync(path.relative(__dirname, 'bar.md'), content)

非阻塞的文件读写

Node 中认为 64 KB 以下是小文件。

js
const fs = require('fs')
const path = require('path')

// 全部先读取到内存中,再写进去。
// 不能读取大文件,如果文件过大,会淹没可用内存或内存溢出。
fs.readFile(path.resolve(__dirname, '11-流.md'), function (err, data) {
  if (err) {
    return console.log(err)
  }

  fs.writeFile(path.resolve(__dirname, 'copy.md'), data, function (err) {
    if (err) {
      return console.log(err)
    }

    console.log('copy ok')
  })
})
js
const fs = require('fs')
const path = require('path')

const buffer = Buffer.alloc(3)

// r - read
// w - write
// a - append,追加内容,如果文件不存在会创建。
// r+ - 以读为基础,要求文件必须存在。
// w+ - 以写为基础,文件不存在也可以操作。
fs.open(path.resolve(__dirname, 'foo.md'), 'r', function (err, fd) {
  // fd => file description,用来描述对这个文件做什么操作,是一个数字,从 3 开始递增。
  // 读取文件,从 Buffer 的第 0 个位置写入,写 3 个,读取文件的位置是 0。
  fs.read(fd, buffer, 0, 3, 0, function (err, bytesRead) {
    // bytesRead 表示真实读取到的个数
    
    // 销毁读取的结果
    fs.open(path.resolve(__dirname, 'bar.md'), 'w', function (err, wfd) {
      // 写入文件,从 Buffer 的第 0 个位置读取,读 3 个,写入文件的位置是 0。
      fs.write(wfd, buffer, 0, 3, 0, function (err, written) {
        console.log('write ok')
        fs.close(fd, () => {})
        fs.close(wfd, () => {})
      })
    })
  })
})
js
const fs = require('fs')
const path = require('path')

// 读取 3 个字节再消费 3 个字节 怎么实现?
const size = 3
const buffer = Buffer.alloc(size)
let readOffset = 0
let writeOffset = 0

// 读写可以分开操作,通过发布订阅来解耦。fs 基于流来实现大文件的读取。
// fs 中 createReadStream 和 createWriteStream 基于 Strem 模块实现。
fs.open(path.resolve(__dirname, 'foo.md'), 'r', function (err, fd) {
  fs.open(path.resolve(__dirname, 'bar.md'), 'w', function (err, wfd) {
    const next = function () {
      fs.read(fd, buffer, 0, size, readOffset, function (err, bytesRead) {
        fs.write(wfd, buffer, 0, bytesRead, writeOffset, function (err, written) {
          console.log(bytesRead)
          if (bytesRead) {
            readOffset += bytesRead
            writeOffset += written
            next()
          } else {
            fs.close(fd, () => {})
            fs.close(wfd, () => {})
          }
        })
      })
    }

    next()
  })
})