系统性学习Node.js(5)—手写 fs 核心方法( 三 )


options = getOptions(options, { flag: 'r' })
// 打开文件 ,
// 如果打开失败则直接调用 cb , 传入失败原因
fs.open(path, options.flag, 0o666, (err, fd) => {
if (err) {
cb(err)
return
}
// 申请一个 10 字节的 buffer
const readBuf = Buffer.alloc(10)
// 文件读取的位置
let pos = 0
// 返回值 , 读取到的文件内容
let retBuf = Buffer.alloc(0)
// 读取 fs.open 打开的文件(fd)
// 将文件内容读取到 readBuf 内 (buffer)
// 从 readBuf 的第 0 个字节开始读入 (offset)
// 读取的长度为 readBuf.length (length)
// 从文件的第 pos 个字节开始读取 (postion)
const next = () => {
fs.read(fd, readBuf, 0, readBuf.length, pos, (err, bytesRead) => {
if (err) {
cb(err)
return
}
// bytesRead 为实际读取到的文件字节数
// 当读取不到内容时(bytesRead = 0) , 则代表文件读取完毕
if (!bytesRead) {
fs.close(fd, () => {})
cb(
null,
options.encoding ?
retBuf.toString(options.encoding) :
retBuf
)
return;
}
// 计算下次读取文件的位置
pos += bytesRead
// 将读取到的内容合并到 retBuf 内
retBuf = Buffer.concat([retBuf, readBuf])
// 递归调用
next()
})
}
next()
})
}
fs.writeFile 实现原生方法的使用:
// 将字符串 1 以 utf8 编码的形式写入 w-test1.js 内
fs.writeFile('./w-test1.js', '1', { encoding: 'utf8' },(err) => {})
// 直接写入二进制数据 , 即将 buffer 写入到文件
fs.writeFile('./w-test1.js', Buffer.from('1'), (err) => {})
不多解释了 , 想象着大象就搞得定 , 这里直接把代码贴出来(代码里的注释还是很详细的) 。
const writeFile = (path, data, options, cb) => {
cb = maybeCallback(cb || options)
options = getOptions(options, {
encoding: 'utf8',
mode: 0o666, // 可读写的文件权限
flag: 'w' // 以写文件的形式打开文件
})
// 打开文件
fs.open(path, options.flag, fs.mode, (err, fd) => {
// 判断下写入的类型是否为 buffer
// 如果是字符串则转成 buffer
const buf = Buffer.isBuffer(data) ?
data :
Buffer.from(data, options.encoding)
// 这里我们假设一次只写入 4 个字节
// 如果要写入的字节少于 4 个 , 则取最小值
const writtenLen = buf.length < 4 ? buf.length : 4
// 文件写入的位置
let pos = 0
【系统性学习Node.js(5)—手写 fs 核心方法】 const next = () => {
// 将内容写入到 fs 打开的文件(fd)
// 要被写入的 buffer 为 buf
// 从 buffer 的第 pos 个文章开始写入
// 写入的长度 为 writtenLen
// 从文件的第 pos 个文章开始写入
fs.write(fd, buf, pos, writtenLen, pos, (err, bytesWritten) => {
if (err) {
return cb(err)
}
if (!bytesWritten) {
next()
}
pos += bytesWritten
})
}
next()
})
}
fs.appendFile追加文件
与 writeFile 不同的是 , writeFile 会覆盖之前的内容 , 而 appendFile 是追加内容 。
原生方法的使用方式如下:fs.appendFile('./w-test2.js', '1', (err) => {console.log(err)})


推荐阅读