1. 内置模块之fs模块&path模块

142 阅读4分钟

1. fs文件操作两种方法

  • 异步方法:非阻塞,通过回调函数返回结果。
  • 同步方法:阻塞,直接返回结果(使用 Sync 后缀)。

2. 异步操作文件

2.1 文件写入

//导入模块
const fs = require('fs');

// 写文件
// 参数分别为 文件、内容、回调函数
fs.writeFile('./座右铭.txt', "三人行,必有我师", err=>{
    if (err) {
        console.log(err);
        return ;
    }
    console.log("success");
}) 

2.2 文件追加

//导入模块
const fs = require('fs');

// 追加写文件
fs.appendFile('./座右铭.txt', "四人行呢", err=>{
    if (err) {
        console.log(err);
        return ;
    }
    console.log('追加成功');
})

2.3 流式写入(适合频繁写入场景)

//导入模块
const fs = require('fs');

// 创建写入流对象
const ws = fs.createWriteStream('./静夜思.txt');

// 写
ws.write('床前明月光\r\n');
ws.write('疑是地上霜\r\n');
ws.write('举头望明月\r\n');
ws.write('低头思故乡\r\n');

// 关闭
ws.close();

2.4 文件读取

const fs = require('fs');

fs.readFile('./静夜思.txt', 'utf8', (err, data) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log(data);
})

2.5 流式读取

const fs = require('fs');

const readStream = fs.createReadStream('./静夜思.txt', 'utf8');
readStream.on('data', (chunk) => {
    console.log('读取数据:', chunk);
});
readStream.on('end', () => {
    console.log('读取完成');
});

2.6文件复制

const fs = require("fs")

const readStream = fs.createReadStream("./1.txt");
const writeStream = fs.createWriteStream("./2.txt");
readStream.pipe(writeStream);

2.7 文件重命名和移动

const fs = require("fs")

fs.rename('./a.txt', './english/b.txt', (err)=>{
    if (err) throw err;
    console.log('success');
})

2.8 文件删除

const fs = require('fs');

fs.unlink('/静夜思.txt', err => {
    if(err) {
        console.log('删除失败');
        return ;
    }
    console.log('删除成功);
})

// 方法2:调用rm方法
fs.rm('/静夜思.txt', err => {
    if(err) {
        console.log('删除失败');
        return ;
    }
    console.log('删除成功);
})

3. 同步操作文件

// 读取文件
try {
  const data = fs.readFileSync('example.txt', 'utf8');
  console.log('文件内容:', data);
} catch (err) {
  console.error('读取文件出错:', err);
}


// 写文件
try {
  fs.writeFileSync('example.txt', "1234124");
  console.log('文件写入成功');
} catch (err) {
  console.error('写入文件出错:', err);
}

// 追加内容
appendFileSync

// 删除文件
unlinkSync

// 重命名
fs.renameSync(oldPath, newPath)

4. 文件夹操作

方法说明
mkdir/mkdirSync创建文件夹
readdir/readdirSync读取文件夹
rmdir/rmdirSync删除文件夹

4.1 创建文件夹

同步创建 fs.mkdirSync()

const fs = require('fs');

try {
  fs.mkdirSync('newFolder');
  console.log('文件夹创建成功');
} catch (err) {
  console.error('创建文件夹出错:', err);
}

异步创建 fs.mkdir()

fs.mkdir('newFolder', (err) => {
  if (err) {
    console.error('创建文件夹出错:', err);
    return;
  }
  console.log('文件夹创建成功');
});

创建多级目录

// 使用 recursive 选项
fs.mkdir('path/to/new/folder', { recursive: true }, (err) => {
  if (err) throw err;
  console.log('多级文件夹创建成功');
});

4.2 读取文件夹

同步读取 fs.readdirSync()

try {
  const files = fs.readdirSync('folderName');
  console.log('文件夹内容:', files);
} catch (err) {
  console.error('读取文件夹出错:', err);
}

异步读取 fs.readdir()

fs.readdir('folderName', (err, files) => {
  if (err) {
    console.error('读取文件夹出错:', err);
    return;
  }
  console.log('文件夹内容:', files);
});

读取带文件类型的信息

fs.readdir('folderName', { withFileTypes: true }, (err, dirents) => {
  if (err) throw err;
  dirents.forEach(dirent => {
    console.log(dirent.name, dirent.isDirectory() ? '(目录)' : '(文件)');
  });
});

4.3 删除文件夹

同步删除 fs.rmdirSync()

try {
  fs.rmdirSync('folderName');
  console.log('文件夹删除成功');
} catch (err) {
  console.error('删除文件夹出错:', err);
}

异步删除 fs.rmdir()

fs.rmdir('folderName', (err) => {
  if (err) {
    console.error('删除文件夹出错:', err);
    return;
  }
  console.log('文件夹删除成功');
});

删除非空文件夹

Node.js 14+ 提供了 fs.rm() 或 fs.rmSync() 方法,可以递归删除非空文件夹:

// 异步删除非空文件夹
fs.rm('folderName', { recursive: true, force: true }, (err) => {
  if (err) throw err;
  console.log('文件夹及其内容已删除');
});

// 同步删除非空文件夹
fs.rmSync('folderName', { recursive: true, force: true });

4.4 检查文件夹是否存在

// 使用 fs.existsSync() (已废弃,但仍可用)
if (fs.existsSync('folderName')) {
  console.log('文件夹存在');
} else {
  console.log('文件夹不存在');
}

// 推荐方式:使用 fs.access() 或 fs.accessSync()
try {
  fs.accessSync('folderName');
  console.log('文件夹存在');
} catch (err) {
  console.log('文件夹不存在');
}

4.5 获取文件/文件夹状态

fs.stat('path', (err, stats) => {
  if (err) throw err;
  console.log('是否是目录:', stats.isDirectory());
  console.log('创建时间:', stats.birthtime);
  console.log('大小:', stats.size);
});

5 相对路径bug

相对路径中的当前目录,指的是命令行的工作目录,而非是文件的所在目录 所以当命令行工作目录与文件所在目录不一样时,会出现一些bug

使用__dirname变量解决,这个代表的是可执行文件的所在绝对路径,利用这个变量再拼接上相对路径,就可以精准找到文件。

6. path模块

path 模块是 Node.js 提供的用于处理文件和目录路径的核心模块,它提供了一系列实用方法来处理文件路径,确保跨平台兼容性。

6.1 路径解析 path.resolve()

将路径或路径片段解析为绝对路径

path.resolve('/foo/bar', './baz');
// 返回: '/foo/bar/baz'

path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果当前工作目录是 /home/myself/node
// 返回: '/home/myself/node/wwwroot/static_files/gif/image.gif'

6.2 sep获取系统路径分隔符

path.sep; // 路径分隔符
// POSIX: '/'
// Windows: '\\'

'foo/bar/baz'.split(path.sep);
// POSIX: ['foo', 'bar', 'baz']
// Windows: ['foo/bar/baz'] (注意Windows上实际行为可能不同)

6.3 路径解析对象 path.parse()

path.parse('/home/user/dir/file.txt');
/*
返回:
{
  root: '/',
  dir: '/home/user/dir',
  base: 'file.txt',
  ext: '.txt',
  name: 'file'
}
*/

6.4 获取路径名 path.dirname()

path.dirname('/foo/bar/baz.html');
// 返回: '/foo/bar'

6.5 ### 获取扩展名 path.extname()

path.extname('index.html');
// 返回: '.html'

path.extname('index.coffee.md');
// 返回: '.md'

path.extname('index');
// 返回: ''

6.6 获取文件名 path.basename()

path.basename('/foo/bar/baz.html');
// 返回: 'baz.html'

path.basename('/foo/bar/baz.html', '.html');
// 返回: 'baz'