创建路径和文件写就绪写流(如果 NodeJS 中不存在路径和文件)



基于其他问题(如下(和文档,我有以下内容,当它不存在时,应该创建一个新的目录和文件,或者当它存在时替换它:

require('fs')
;(async ()=>{
//ref 1
fs.closeSync(fs.openSync('./newpath/newfile', 'w')); // make sure path and file exists
let mystream = fs.createWriteStream('./newpath/newfile',{encoding:'binary',flags : 'w'})
//ref2
await new Promise(r=> mystream.on('open'),(r)=>{r()})
let whyohwhy = Buffer.from("Should this be easy?")
mystream.write(whyohwhy,'binary',e=>console.log('Written to ./newpath/newfile'))
})();

参考文献1:https://stackoverflow.com/a/12809419/1461850

参考文献2:https://stackoverflow.com/a/12906805/1461850

其他";几乎";问题:

如果不存在,则创建文件和文件夹

仅当文件没有';Node.js 中不存在

如果没有创建文件';不存在

唉,我得到这个错误

Promise {
<rejected> Error: ENOENT: no such file or directory, open './newpath/newfile'
at Object.openSync (fs.js:498:3)
at REPL10:3:17
at REPL10:9:3
at Script.runInThisContext (vm.js:133:18)
at REPLServer.defaultEval (repl.js:486:29)
at bound (domain.js:416:15)
at REPLServer.runBound [as eval] (domain.js:427:12)
at REPLServer.onLine (repl.js:819:10)
at REPLServer.emit (events.js:388:22)
at REPLServer.emit (domain.js:470:12) {
errno: -4058,
syscall: 'open',
code: 'ENOENT',
path: './newpath/newfile'
}
}
> (node:13988) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open './newpath/newfile'
at Object.openSync (fs.js:498:3)
at REPL10:3:17
at REPL10:9:3
at Script.runInThisContext (vm.js:133:18)
at REPLServer.defaultEval (repl.js:486:29)
at bound (domain.js:416:15)
at REPLServer.runBound [as eval] (domain.js:427:12)
at REPLServer.onLine (repl.js:819:10)
at REPLServer.emit (events.js:388:22)
at REPLServer.emit (domain.js:470:12)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:13988) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:13988) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.


是否有一种简单/规范的方法来创建写初始化的writeStream,如果不存在,则创建路径/文件,如果存在则替换路径/文件



刚刚发现了这个。我所做的是像这样扩展Writable

class AsyncPathMakerWriteStream extends Writable {
constructor (basePath, fileName) {
super()
this.basePath = basePath
this.fileName = fileName
this.fd = null
}
_construct (callback) {
fs.mkdir(this.basePath, { recursive: true }, err => {
if (err) {
callback(err)
} else {
fs.open(join(this.basePath, this.fileName), (err, fd) => {
if (err) {
callback(err)
} else {
this.fd = fd
callback()
}
})
}
})
}
_write (chunk, encoding, callback) {
fs.write(this.fd, chunk, callback)
}
_destroy (err, callback) {
if (this.fd) {
fs.close(this.fd, (er) => callback(er || err))
} else {
callback(err)
}
}
}

数据将在流中进行内部缓冲,直到文件打开而不阻塞主线程。

如果您所需要做的只是确保路径存在,那么扩展Writable可能有点太多了。

这里有另一个解决方案:

const { PassThrough } = require('node:stream')
const fs = require('node:fs')
const mystream = new PassThrough()
// you can now start writing to mystream, data will be buffered
mystream.write('ho ho ho')
ensurePathExistsAndOtherAsyncStuff()
.then(() => {
const fileWriteStream = fs.createWriteStream('./newpath/newfile',{encoding:'binary',flags : 'w'})
mystream.pipe(fileWriteStream, { 
end: true // closing mystream will close fileWriteStream
})
})

我用fs-extra模块的ensureFile功能做到了这一点:

let fs = require('fs-extra')
;(async ()=>{
await fs.ensureFile('./newpath/newfile').catch(err=>console.log)
let mystream = fs.createWriteStream('./newpath/newfile',{encoding:'binary',flags : 'w'})
let whyohwhy = Buffer.from("Why can't this just be easy!")
mystream.write(whyohwhy,'binary',e=>console.log('Written to ./newpath/newfile'))
})();

然而,我对其他方式感兴趣…