文件路径

import path from 'node:path';
 
const notes = '/users/joe/notes.txt';
 
path.dirname(notes); // /users/joe
path.basename(notes); // notes.txt
path.extname(notes); // .txt
 
// 可以通过指定 basename 的第二个参数来获取不带扩展名的文件名
path.basename(notes, path.extname(notes)); // notes
  • dirname:目录,从开头截取到最后一个路径分割符(/\
  • basename:文件名,从最后一个路径分割符截取到最后
  • extname:扩展名(包含 .),从最后一个 . 截取到最后
const name = 'joe';
path.join('/', 'users', name, './notes.txt'); // '/users/joe/notes.txt'
 
path.resolve('joe.txt'); // '/Users/joe/joe.txt'
// 没有绝对路径,则绝对路径为当前工作目录
 
path.resolve('/etc', 'joe.txt'); // '/etc/joe.txt'
// 有绝对路径,就用提供的绝对路径
 
path.normalize('/users/joe/..//test.txt'); // '/users/test.txt'
  • path.join():连接路径的两个或多个部分
  • path.resolve():获得相对路径的绝对路径计算
  • path.normalize():规范化路径

注意:上面的方法都不会检查路径是否存在,它们只是根据获得的信息计算出一条路径

文件信息

  • fs.exists(path):检查文件或文件夹是否存在
  • fs.access(path):检查文件或文件夹是否存在,并且是否有权限访问

异步回调:

import fs from 'node:fs';
 
fs.stat('/Users/joe/test.txt', (err, stats) => {
  if (err) {
    console.error(err);
  }
  // we have access to the file stats in `stats`
});

同步阻塞:

import fs from 'node:fs';
 
try {
  const stats = fs.statSync('/Users/joe/test.txt');
} catch (err) {
  console.error(err);
}

异步 Promise:

import fs from 'node:fs/promises';
 
try {
  const stats = await fs.stat('/Users/joe/test.txt');
} catch (err) {
  console.log(err);
}
  • stats.isFile():是文件
  • stats.isDirectory():是目录(文件夹)
  • stats.isSymbolicLink():是符号链接(软链接)
  • stats.size:文件大小,以字节为单位

文件描述符

在与文件系统中的文件进行交互之前,必须获取文件描述符

文件描述符是对打开文件的引用,是使用 fs 模块提供的 open() 方法打开文件返回的数字。该数字(fd)唯一标识操作系统中打开的文件

import fs from 'node:fs';
 
fs.open('/Users/joe/test.txt', 'r', (err, fd) => {
  // fd is our file descriptor
});

第二个参数是一个标记,经常使用的标记:

  • 'a':打开文件进行追加。如果文件不存在,则创建该文件
  • 'a+':打开文件进行读取和追加。如果文件不存在,则创建该文件
  • 'r':打开文件进行读取。如果文件不存在,则会发生异常
  • 'r+':打开文件进行读写。如果文件不存在,则会发生异常
  • 'w':打开文件进行写入。文件被创建(如果不存在)或截断(如果存在)
  • 'w+':打开文件进行读写。文件被创建(如果不存在)或截断(如果存在)

读取文件

import fs from 'node:fs';
 
fs.readFile('/Users/joe/test.txt', 'utf8', (err, data) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(data);
});

一次性读取文件的完整内容到内存,这意味着大文件将对内存消耗和程序执行速度产生重大影响。在这种情况下,更好的选择是使用流读取文件内容:

写入文件

import fs from 'node:fs';
 
const content = 'Some content!';
 
fs.writeFile('/Users/joe/test.txt', content, err => {
  if (err) {
    console.error(err);
  } else {
    // file written successfully
  }
});

默认情况下,如果文件已存在,此 API 将替换该文件的内容,可以通过指定标志来修改写入模式:

fs.writeFile('/Users/joe/test.txt', content, { flag: 'a+' }, err => {});

或者直接调用 appendFile 函数进行追加:

import fs from 'node:fs';
 
const content = 'Some content!';
 
fs.appendFile('file.log', content, err => {
  if (err) {
    console.error(err);
  } else {
    // done!
  }
});
  • fs.writeFile:覆盖写入
  • fs.appendFile:追加写入

处理文件夹

  • fs.mkdir(path):创建文件夹
  • fs.readdir(path):读取文件夹的内容,包括文件和子文件夹,并返回它们的相对路径
  • fs.rename(path, newName, cb)
  • fs.rmdir(path):删除文件夹