以文件读取为例,在NodeJS中有两种类型的读写文件的方式,一种是通过fs.readFile()
和fs.writeFile()
方法
-
fs.readFile()
方法的参数,为文件的名字和一个回调函数,其中回调函数接收两个参数:-
err
:如果读取错误,则返回一个错误对象; -
data
:如果读取成功,则返回读取后的数据;
-
-
fs.writeFile()
方法的参数-
fileName
:要写入的目标文件; -
data
:要写入的数据; -
option
:写入的配置参数; -
callback
:写入成功后的回调函数,接收寄一个参数err
,如果写入文件失败,则用err
,接收错误对象
-
示例:
const fs = require('fs')
const path = require('path')
let fileName1 = path.resolve(__dirname, 'data.txt')
let fileName2 = path.resolve(__dirname, 'data_bar_02.txt')
fs.readFile(fileName1, (err, data) => {
if (err) {
console.error(err)
return
}
fs.writeFile(fileName2, data, {
flags: 'a'
}, (err) => {
if (err) {
console.error(err)
return
}
console.log('clone done')
})
})
这里就引出了在服务器端读取文件的问题,由于计算机为单个的NodeJS进程分配的系统资源是有限制的,单个NodeJS服务进程最大被分配的内存为3GB,用上面的这种方式读取和写入文件,是把读取后和要写入的数据整体作为变量,存储在计算机的内存中,如果目标文件体积过大,就会直接完全占用系统资源,造成服务崩溃。所以在NodeJS中,通常使用stream技术,进行IO操作。
通过stream操作IO
在NodeJS中,通过stream技术,读取和写入文件,主要是通过fs.createReadStream()
和createWriteStream()
方法
// 利用stream操作文件
const fs = require('fs')
const path = require('path')
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname,'data_bak.txt')
const readStream = fs.createReadStream(fileName1)
const writeStream = fs.createWriteStream(fileName2)
readStream.pipe(writeStream)
readStream.on('data', (chunk) => {
console.log(chunk.toString())
})
readStream.on('end', () => {
console.log('copy done')
})
使用数据流方式读取操作IO,将文件分段读取并逐步写入目标文件,可以有效降低服务器的系统开销。再看下面的例子:
const http = require('http')
const fs = require('fs')
const path = require('path')
const app = http.createServer((req, res) => {
if (req.method === 'GET') {
let fileName = path.resolve(__dirname, 'data.txt')
let readStream = fs.createReadStream(fileName)
readStream.pipe(res)
}
})
app.listen(8000, () => {
console.log('running on 8000')
})
服务器IO操作的瓶颈,不止有硬件瓶颈,同时还有网络瓶颈,使用数据流的形式来操作文件读取的方式在网络流媒体(在线视频,音乐网站,视频直播,短视频···)等需要对较大文件进行读写操作的场景下,可以有效降低网络负载,并减少用户等待时间,提高用户体验。
网友评论