系统性学习Node.js(5)—手写 fs 核心方法( 二 )
fs.open(path, options.flag, 0o666, (err, fd) => {
if (err) {
cb(err)
return
}
})
}
const maybeCallback = cb => {
if (typeof cb === 'function') {
return cb
}
throw new TypeError('Callback must be a function')
}
const getOptions = (options, defaultOptions = null) => {
if (
options === null ||
options === undefined ||
typeof options === 'function'
) {
return defaultOptions
}
return Object.assign({}, defaultOptions, options)
}
2. 把大象放入冰箱(读取文件)// 申请一个 10 字节的 buffer
const readBuf = Buffer.alloc(10)
// 文件读取的位置
let pos = 0
// 读取 fs.open 打开的文件(fd)
// 将文件内容读取到 readBuf 内 (buffer)
// 从 readBuf 的第 0 个字节开始读入 (offset)
// 读取的长度为 readBuf.length (length)
// 从文件的第 pos 个字节开始读取 (postion)
fs.read(fd, readBuf, 0, readBuf.length, pos, (err, bytesRead) => {
if (err) {
cb(err)
return
}
console.log(readBuf) // 文件里的内容已写入到 readBuf
cb(readBuf)
})
现在我们已经将内容读取到 readBuf 内 , 并通过 cb 传给函数调用者 , 但是存在着一个严重的问题 , 那就是我们只读取了 10 字节的内容 , 显然文件的内容是非常有可能比 10 字节要多 。
那有没有办法一次性将文件的内容全部读取出来呢?
I'm sorry~~~ 木有办法 , 因为我们并拿不到文件的长度 , 所以就老老实实一点一点的将内容读出来吧
所以我们改进代码如下:
// 申请一个 10 字节的 buffer
const readBuf = Buffer.alloc(10)
// 文件读取的位置
let pos = 0
// 返回值 , 读取到的文件内容
let retBuf = Buffer.alloc(0)
const next = () => {
// 读取 fs.open 打开的文件(fd)
// 将文件内容读取到 readBuf 内 (buffer)
// 从 readBuf 的第 0 个字节开始读入 (offset)
// 读取的长度为 readBuf.length (length)
// 从文件的第 pos 个字节开始读取 (postion)
fs.read(fd, readBuf, 0, readBuf.length, pos, (err, bytesRead) => {
if (err) {
cb(err)
return
}
// bytesRead 为实际读取到的文件字节数
// 当读取不到内容时(bytesRead = 0) , 则代表文件读取完毕
if (!bytesRead) {
cb(
null,
options.encoding ?
retBuf.toString(options.encoding) :
retBuf
)
return;
}
// 计算下次读取文件的位置
pos += bytesRead
// 将读取到的内容合并到 retBuf 内
retBuf = Buffer.concat([retBuf, readBuf])
// 递归调用
next()
})
}
next()
我们将读取文件的操作封装成一个方法 , 然后递归调用 , 直到读取不到内容为止 。
3. 关闭冰箱这一步超简单
if (!bytesRead) {
fs.close(fd, () => {})
cb(
null,
options.encoding ?
retBuf.toString(options.encoding) :
retBuf
)
return;
}
完整代码const readFile = (path, options, cb) => {
// 尝试获取 cb , 如果获取不到则抛出错误
// 由于 options 是非必填参数 , 所以它有可能是回调函数
cb = maybeCallback(cb || options)
// 获取 options , 如果未穿 options , 则取默认参数
- 学习了大数据开发知识,但是面试却屡屡碰壁该怎么办
- 大一上学期学了Python,希望主攻大数据还应该学习什么语言
- 大一下学期转入计算机专业,寒假期间该重点学习什么内容
- 从运维岗转向开发岗,该选择学习Java还是Python
- 想学习编程,该从哪开始
- 当前学习大数据是否都需要学习Java
- 学习|AWS如何为AI工作者赋能?
- 孩子学习没兴趣没动力 不妨试试讯飞智能学习机X2 Pro
- 本科生想从事人工智能岗位,该如何制定学习规划
- 浩林教育:科技赋能让学习有趣且有效
