Skip to content

Node.js 文件系统 ​

fs 模块用于文件系统操作,提供同步和异步两种方式。

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

同步 vs 异步:

  • 同步(带 Sync):有返回值,用 try...catch 捕获错误
  • 异步(回调):通过回调函数获取结果

文件读写 ​

完全读写 ​

js
// 读取文件
fs.readFile('file.txt', (err, data) => {
  if (err) throw err
  console.log(data.toString())  // data 默认为 Buffer
})

// 同步读取
const data = fs.readFileSync('file.txt', 'utf-8')

// 写入文件(覆盖)
fs.writeFile('file.txt', 'Hello World', (err) => {
  if (err) throw err
})

// 同步写入
fs.writeFileSync('file.txt', 'Hello World')

// 追加内容
fs.appendFile('file.txt', '\n新内容', (err) => {
  if (err) throw err
})

// 同步追加
fs.appendFileSync('file.txt', '\n新内容')

// 拷贝文件
fs.copyFile('source.txt', 'target.txt', (err) => {
  if (err) throw err
})

// 删除文件
fs.unlink('file.txt', (err) => {
  if (err) throw err
})
// 读取文件
fs.readFile('file.txt', (err, data) => {
  if (err) throw err
  console.log(data.toString())  // data 默认为 Buffer
})

// 同步读取
const data = fs.readFileSync('file.txt', 'utf-8')

// 写入文件(覆盖)
fs.writeFile('file.txt', 'Hello World', (err) => {
  if (err) throw err
})

// 同步写入
fs.writeFileSync('file.txt', 'Hello World')

// 追加内容
fs.appendFile('file.txt', '\n新内容', (err) => {
  if (err) throw err
})

// 同步追加
fs.appendFileSync('file.txt', '\n新内容')

// 拷贝文件
fs.copyFile('source.txt', 'target.txt', (err) => {
  if (err) throw err
})

// 删除文件
fs.unlink('file.txt', (err) => {
  if (err) throw err
})

不完全读写(分段操作大文件) ​

适用于大文件,可以控制读取位置和长度。

打开文件 ​

js
// 异步打开
fs.open('file.txt', 'r', (err, fd) => {
  // fd 为文件句柄
})

// 同步打开
const fd = fs.openSync('file.txt', 'r')
// 异步打开
fs.open('file.txt', 'r', (err, fd) => {
  // fd 为文件句柄
})

// 同步打开
const fd = fs.openSync('file.txt', 'r')

文件系统标志:

标志说明
r读取,文件不存在报错
r+读写,文件不存在报错
w写入,文件不存在则创建,存在则覆盖
w+读写,文件不存在则创建
a追加,文件不存在则创建
a+读取并追加,文件不存在则创建

读取文件 ​

js
const buf = Buffer.alloc(6)

fs.open('file.txt', 'r', (err, fd) => {
  // fd, buffer, offset, length, position, callback
  fs.read(fd, buf, 0, 3, 0, (err, bytesRead, buffer) => {
    console.log(buffer.toString())
    fs.close(fd)
  })
})
const buf = Buffer.alloc(6)

fs.open('file.txt', 'r', (err, fd) => {
  // fd, buffer, offset, length, position, callback
  fs.read(fd, buf, 0, 3, 0, (err, bytesRead, buffer) => {
    console.log(buffer.toString())
    fs.close(fd)
  })
})

写入文件 ​

js
fs.open('file.txt', 'w', (err, fd) => {
  fs.write(fd, Buffer.from('Hello'), 0, 5, 0, (err) => {
    fs.close(fd)
  })
})
fs.open('file.txt', 'w', (err, fd) => {
  fs.write(fd, Buffer.from('Hello'), 0, 5, 0, (err) => {
    fs.close(fd)
  })
})

目录操作 ​

js
// 创建目录(recursive 递归创建)
fs.mkdir('a/b/c', { recursive: true }, (err) => {})

// 读取目录
fs.readdir('dir', (err, files) => {})

// 删除目录(只能删除空目录)
fs.rmdir('dir', (err) => {})

// 判断目录是否存在
fs.existsSync('path')  // true / false
// 创建目录(recursive 递归创建)
fs.mkdir('a/b/c', { recursive: true }, (err) => {})

// 读取目录
fs.readdir('dir', (err, files) => {})

// 删除目录(只能删除空目录)
fs.rmdir('dir', (err) => {})

// 判断目录是否存在
fs.existsSync('path')  // true / false

递归删除非空目录 ​

js
const path = require('path')

function removeDir(dirPath) {
  const files = fs.readdirSync(dirPath)
  files.forEach((file) => {
    const curPath = path.resolve(dirPath, file)
    if (fs.statSync(curPath).isDirectory()) {
      removeDir(curPath)
    } else {
      fs.unlinkSync(curPath)
    }
  })
  fs.rmdirSync(dirPath)
}
const path = require('path')

function removeDir(dirPath) {
  const files = fs.readdirSync(dirPath)
  files.forEach((file) => {
    const curPath = path.resolve(dirPath, file)
    if (fs.statSync(curPath).isDirectory()) {
      removeDir(curPath)
    } else {
      fs.unlinkSync(curPath)
    }
  })
  fs.rmdirSync(dirPath)
}

文件状态 ​

js
fs.stat('file.txt', (err, stats) => {
  stats.isDirectory()  // 是否为目录
  stats.isFile()       // 是否为文件
  stats.size           // 文件大小(字节)
  stats.mtime          // 修改时间
})

// 同步
const stats = fs.statSync('file.txt')
fs.stat('file.txt', (err, stats) => {
  stats.isDirectory()  // 是否为目录
  stats.isFile()       // 是否为文件
  stats.size           // 文件大小(字节)
  stats.mtime          // 修改时间
})

// 同步
const stats = fs.statSync('file.txt')

fs-extra ​

第三方库,提供了更便捷的文件操作:

bash
npm install fs-extra
npm install fs-extra
js
const fs = require('fs-extra')

// 自动创建不存在的目录
fs.copySync('/tmp/myfile', '/tmp/mynewfile')

// 直接读写 JSON(自动序列化/反序列化)
fs.outputJsonSync('./data.json', { key: 'value' }, { spaces: 2 })
const data = fs.readJSONSync('./data.json')
const fs = require('fs-extra')

// 自动创建不存在的目录
fs.copySync('/tmp/myfile', '/tmp/mynewfile')

// 直接读写 JSON(自动序列化/反序列化)
fs.outputJsonSync('./data.json', { key: 'value' }, { spaces: 2 })
const data = fs.readJSONSync('./data.json')