fs模块是Node.js中内置的用于文件系统操作的模块,它提供了各种方法和函数,用于处理文件和目录。
目录
1.写入文件
2.讲讲同步和异步
3.追加写入
4.读取文件
5.文件重命名及文件移动
6.文件删除
7.文件夹的操作
1.写入文件
普通的写入方法:
用到的是fs模块的fs.writeFile()和fs.writeFileSync(),其中前者是异步方法,后者是同步方法。
语法格式:下面的代码执行会找到对应的文件写入str字符串,如果没有该文件,则会自动创建文件并写入,但是这种写入会将原来的文件直接覆盖掉。
异步方法:
const fs = require('fs')
let str = 'hello'
//会直接覆盖写入,如果没有文件夹会自动创建新的文件夹
fs.writeFile('1.txt', str, (err) => {
if (err) {
console.log(err)
return
}
console.log('写入成功1')
})
同步方法:
因为同步方法是没有错误的回调函数的,所以这里我们需要手动的去接收错误
const fs = require('fs')
try {
fs.writeFileSync('1.txt', '11223344')
console.log('文件写入成功')
} catch (error) {
console.error('文件写入失败:', error)
}
流式写入:
const fs = require('fs')
let ws = fs.createWriteStream('1.txt')
ws.write('111\n')
ws.write('222\n')
ws.close()
流式写入和普通写入的区别:
-
写入方式:普通的写入文件方法是一次性将要写入的数据加载到内存中,然后将整个数据块写入文件。而流式写入文件方法是逐步将数据写入文件,一次只写入一小部分数据。
-
内存占用:普通的写入文件方法在写入数据之前需要将所有数据加载到内存中,因此在写入大量数据时,可能会占用较多的内存。而流式写入文件方法逐步写入数据,只需要一小部分数据存在内存中,因此对内存的占用较少。
-
扩展性:普通的写入文件方法适用于小数据量的写入,而流式写入文件方法适用于大数据量或者需要实时写入的场景。流式写入可以实时将数据写入文件,适用于处理大型文件或需要持续写入的情况,例如日志记录器或实时数据流。
-
性能和效率:普通的写入文件方法在写入大量数据时可能会有较长的等待时间,因为需要一次性将所有数据写入。而流式写入文件方法通过逐步写入数据流实现实时写入,并在处理大量数据时具有更好的性能和效率。
综上所述,普通的写入文件方法适用于较小数据量的一次性写入,而流式写入文件方法适用于需要处理大量数据或实时写入的情况。流式写入文件方法可以提供更好的性能和扩展性,并且在数据量较大时对内存的占用较少。
2.讲讲同步和异步
大家其实可以看到上面的写入方法一种是同步一种是异步,它们有什么区别呢,又或者什么时候该用什么呢?
执行流程:
js代码的执行流程大家应该都清楚,是自上而下顺序执行的,同步就是这样,他是按照顺序来执行的,即在调用一个同步方法时,程序会等待该方法完成后再继续执行下一条语句。而异步方法是非阻塞的,它会立即返回,不会等待操作完成。异步方法通常会接受一个回调函数或返回一个 Promise 对象,当操作完成时,会通过回调函数或 Promise 的处理机制来处理结果。
我们可以通过下面的代码例子来看看执行流程
const fs = require('fs')
let str = 'hello'
//会直接覆盖写入,如果没有文件夹会自动创建新的文件夹
fs.writeFile('1.txt', str, (err) => {
if (err) {
console.log(err)
return
}
console.log('异步写入成功')
})
try {
fs.writeFileSync('1.txt', '11223344')
console.log('同步写入成功')
} catch (error) {
console.error('文件写入失败:', error)
}
console.log('全部代码执行完毕')
可以看到在同步写入完成后才执行后面的代码,而异步方法是最后在执行的,他不会影响整个代码的执行流程,由此可以做出假设,假如我们写入的文件非常大,使用同步方法的话就会让代码暂时陷入阻塞的情况,而异步不会存在这样的问题。
由此可以得出结论,同步方法可以更加方便和直观,特别是在简单的脚本或处理逻辑较为简单的程序中,但是如果处理的是大文件,建议使用异步方法。
3.追加写入
异步方法:
我们前面的写入文件都是覆盖写入,执行后前面的文件就被覆盖了,要想实现追加写入,需要用到下面的方法,其中的\r\n都是换行的意思
const fs = require('fs')
fs.appendFile('1.txt', '\r\n111', (err) => {
if (err) {
console.log(err)
return
}
console.log('追加成功')
})
同步方法:
try {
fs.appendFileSync('1.txt', '\r\n222')
console.log('同步追加成功')
} catch (error) {
console.error('文件写入失败:', error)
}
4.读取文件
读取文件也是存在同步和异步的
const fs = require('fs')
//异步读取
fs.readFile('./1.txt', (err, data) => {
if (err) {
console.log(err)
return
}
console.log(data.toString())
})
//同步读取
let data = fs.readFileSync('./1.txt', 'utf-8')
console.log(data.toString())
流式读取:
const fs = require('fs')
let rs = fs.createReadStream('./1.txt')
rs.on('data', (chunk) => {
console.log(chunk.toString())
})
rs.on('end', () => {
console.log('读取完成')
})
rs.on('error', (err) => {
console.log(err)
})
流式读取和普通的读取方法最显著的区别仍然是速度的问题
5.文件重命名及文件移动
文件重命名
const fs = require('fs')
fs.rename('./1.txt', './修改.txt', (err) => {
if (err) {
console.log(err)
return
}
console.log('重命名成功')
})
文件的移动
其实运用的还是重命名的方法,进行位置移动
fs.rename('./修改.txt', '../test/1.txt', (err) => {
if (err) {
console.log(err)
return
}
console.log('重命名成功')
})
6.文件删除
二种方法均可
const fs = require('fs')
fs.unlink('./2.txt', (err) => {
if (err) {
console.log(err)
return
}
console.log('删除成功')
})
fs.rm('./1.txt', (err) => {
if (err) {
console.log(err)
return
}
console.log('删除成功')
})
7.文件夹的操作
创建文件夹
const fs = require('fs')
fs.mkdir('./html', (err) => {
if (err) {
console.log(err)
return
}
console.log('创建成功')
})
递归创建,即为创建多层结构的文件夹
const fs = require('fs')
//递归创建
fs.mkdir('./a/b/c', { recursive: true }, (err) => {
if (err) {
console.log(err)
return
}
console.log('创建成功')
})
读取文件夹目录内容
const fs = require('fs')
//读取文件夹
fs.readdir('../fs模块', (err, files) => {
if (err) {
console.log(err)
return
}
console.log(files)
})
运行结果
删除文件夹(只能删除单层结构的文件夹)
//删除文件夹
fs.rmdir('./html', (err) => {
if (err) {
console.log(err)
return
}
console.log('删除成功')
})
递归删除多层结构的文件夹
const fs = require('fs')
//递归删除 官方不建议使用此方法,未来会被删除
fs.rmdir('./html', { recursive: true }, (err) => {
if (err) {
console.log(err)
return
}
console.log('删除成功')
})
//官方建议删除方法
fs.rm('./a', { recursive: true }, (err) => {
if (err) {
console.log(err)
return
}
console.log('删除成功')
})