node 内置模块之fs

本地文件操作模块 fs

fs 模块对文件的操作有异步和同步两种方式,例如:readFile() 和 readFileSync()

区别:

  • 同步调用会阻塞代码的执行,异步不会
  • 异步调用会将读取任务下达到任务队列,知道任务执行完成才会回调
  • 异常处理:同步必须要使用 try catch 方式,异步可以使用回调函数的第一个参数 err 【重要】

文件读取

方法 说明
readFile 异步读取
readFileSync 同步读取
createReadStream 流式读取
const fs = require('fs')

// 异步
const data

try{
    data = fs.readFileSync('./file1.txt','utf8')
    console.log(data)
} catch(err) {
    console.error('读取文件错误:' + err.message)
}

// 输出:
文件内容:Hello World!

// 同步
fs.readFile('./file1.txt','utf8',(err, dataStr) => {
    if(err) return console.log('读取文件错误:' + err.message)
    console.error(dataStr)
})

// 输出:
文件内容:Hello World!

从 Node.js 14 开始,fs 模块提供了两种使用基于 promises 的文件系统的方法。这些 promises 可以通过 require('fs').promisesrequire('fs/promises') 获得

import { readFile } from 'fs/promises';

try {
  const contents = await readFile(filePath, { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  console.error(err.message);
}

流式

const fs = require('fs')

let rs = fs.createReadStream(__dirname + '/grades.txt')

rs.on('data', chunk => {
    console.log(chunk, chunk.length)
})
rs.on('end', () => console.log('ok'))

文件写入

方法 说明
writeFile 异步写入
writeFileSync 同步写入
appendFile / appendFileSync 追加写入
createWriteStream 流式写入

如果文件不存在,则创建文件,如果文件存在,则覆盖文件内容

const fs = require('fs');
// 异步
fs.writeFile('./fileWrite.txt', 'hello world', 'utf8', function(err){
    if(err) throw err;
    console.log('文件写入成功');
});
// 同步
try{
    fs.writeFileSync('./fileForWrite1.txt', 'hello world', 'utf8');
    console.log('文件写入成功');
}catch(err){
    throw err;
}

追加写入

// 异步
fs.append('./grades.txt', 'hello world', err =>{
    if(err) throw err
    console.log('追加成功')
})

// 同步
fs.appendFileSync('./grades.txt','\r\nHello World')

promises

import { writeFile } from 'fs/promises';

try {
  const contents = await writeFile('message.txt', 'hello world', { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  console.error(err);
}

流式写入

let ws = fs.createWriteStream('./观书有感.txt')

//写入数据到流
ws.write('半亩方塘一鉴开\r\n')
ws.write('天光云影共徘徊\r\n')
ws.write('问渠那得清如许\r\n')
ws.write('为有源头活水来\r\n')

//关闭写入流,表明已没有数据要被写入可写流
ws.end()

程序打开一个文件是需要消耗资源的,流式写入可以减少打开关闭文件的次数

流式写入是用于大文件写入或者频繁写入的场景,writeFile 适合写入频繁较低的场景

文件读写小案例

// grades.txt
小王=100,小李=90,小陈=30,小高=80,小胖=99

// grades.js
const fs = require('fs')

fs.readFile(__dirname + '/grades.txt', 'utf8', (err, dataSrc) => {
    if (err) return console.log('文件读取错误' + err)
    const oldArr = dataSrc.split(',')
    let newArr = []
    oldArr.forEach(item => {
        newArr.push(item.replace('=', ':'))
    })
    const newStr = newArr.join('\r\n')
    // flag:a 表示如果存在该文件,就在文件末尾添加数据,不覆盖原先数据,appendFile
    fs.writeFile(__dirname + '/grades-ok.txt', newStr, { encoding: 'utf8', flag: 'a' }, function (err) { if (err) return console.log('文件写入错误' + err) })
})

// grades-ok.txt
小王:100
小李:90
小陈:30
小高:80
小胖:99

文件移动与重命名

// 异步
fs.rename('./old.txt', './new/new.txt', err =>{
	if(err) throw err
    console.log('移动完成')
})
// 同步,省略了 try catch
fs.renameSync('./old.txt', './new/new.txt')

注意:如果还是移动到当前路径,但是修改了名字,就是重命名

文件删除

const fs = require('fs')
// 使用 unlink 和 unlinkSync
// 异步
fs.unlink('./test.txt', err => {
    if(err) thorw err
    console.log('删除成功')
})

// 同步
fs.unlinkSync('./test.txt')

// 使用 rm 和 rmSync
// 异步
fs.rm('./test.txt', err => {
  if (err) {
    console.log('删除失败')
    return
  }
  console.log('删除成功')
})
// 同步
fs.rmSync('./test.txt')

文件夹操作

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

mkdir 创建文件夹

// 异步创建文件夹
fs.mkdir('./page',err => {
    if(err) throw err
    console.log('创建成功')
})

// 异步递归创建
fs.mkdir('./grandfather/father/son',{recursive: true},err => {
    if(err) throw err
    console.log('递归创建成功')
})

// 同步递归创建
fs.mkdirSync('./grandfather/father/son',{recursive: true})

注意:同步创建已存在文件夹会报错

readdir 读取文件夹

// 异步读取
fs.readdir('./page', (err, data) => {
    if(err) throw err
    console.log(data)
})
// 同步读取 
let data = fs.readdirSync('./page')
console.log(data)

// 读取指定文件夹下的全部文件
// 思路:同步读取该文件夹,遍历读取的文件夹,判断是否为文件或者目录,如果是文件就添加到数组中,如果是目录就递归调用该函数并且将数组拼接,最后返回数组
const fs = require('fs')
const path = require('path')

function readdirAll(dir){
    let results = [path.resolve(__dirname,dir)]
    const files = fs.readdirSync(dir,'utf8')
    files.forEach(file => {
        file = path.resolve(dir,file)
        const stats = fs.statSync(file)
        if(stats.isFile()){
            results.push(file)
        }else if(stats.isDirectory()){
            results = results.concat(readdirAll(file))
        }
    });
    return results
}

console.log(readdirAll('../'))
console.log(readdirAll('./'))

rmdir 删除文件夹

// 异步删除文件夹
fs.rmdir('./page',err=>{
    if(err) throw err
    console.log('删除成功')
})
// 异步递归删除,不推荐
fs.rmdir('./page',{recursive: true},err=>{
    if(err) throw err
    console.log('删除成功')
})
// 同步递归删除文件夹
fs.rmdir('./page',{recursive: true})

// 删除全部文件夹,建议使用
fs.rm('./page',{recursive: true},err=>{
    if(err) {
        console.log(err)
        return
    }
    console.log('删除成功')
})

获取文件夹状态

1.异步:fs.stat(path,callback):
path是一个表示路径的字符串,callback接收两个参数(err,stats),其中stats就是fs.stats的一个实例;

2.同步:fs.statSync(path)
只接收一个path变量,fs.statSync(path)其实是一个fs.stats的一个实例;

方法:

  • stats.isFile():是否为文件
  • stats.iisDirectory():是否为目录(文件夹)
const fs = require('fs'); 
  

statsObj = fs.statSync("test_file.txt"); 
statsObj.isDirectory()); 

注意:上面遍历文件夹下的所有文件也是使用到了文件夹状态和两个方法

posted @ 2023-05-18 10:28  超重了  阅读(202)  评论(0编辑  收藏  举报