只有在Node.js中不存在的情况下才能创build文件
我们有一个我们想要写入文件的缓冲区。 如果文件已经存在,我们需要增加一个索引,然后重试。 有没有办法创build一个文件,如果它不存在,或者我应该只是统计文件,直到我得到一个错误,find一个不存在已经?
例如,我有文件a_1.jpg
和a_2.jpg
。 我想我的方法尝试创builda_1.jpg
和a_2.jpg
,并失败,最后成功创builda_3.jpg
。
理想的方法看起来像这样:
fs.writeFile(path, data, { overwrite: false }, function (err) { if (err) throw err; console.log('It\'s saved!'); });
或者像这样:
fs.createWriteStream(path, { overwrite: false });
在节点的fs
库中是否存在这样的事情?
编辑 :我的问题是,如果有一个单独的function,检查是否存在。 就是这样的:有没有办法在单个文件系统调用中创build一个文件?
当你的直觉正确的猜测,一对exists / writeFile
调用的天真的解决scheme是错误的。 asynchronous代码以不可预知的方式运行。 在特定的情况下是这样
- 有没有文件
a.txt
? – 没有 - (文件
a.txt
由另一个程序创build) - 如果可能,写入
a.txt
。 – 好的。
但是,是的,我们可以在一个电话中做到这一点。 我们正在使用文件系统,因此阅读fs
上的开发者手册是个好主意。 嘿, 这是一个有趣的部分。
'w' – 打开文件写入。 该文件被创build(如果不存在)或被截断(如果存在)。
'wx' – 就像'w'一样,但如果path存在就会失败。
所以我们所要做的只是将wx
添加到fs.open
调用中。 但是,嘿,我们不喜欢fopen
式IO。 让我们再读一下fs.writeFile
。
fs.readFile(filename [,options],callback)#
filenamestring
选项对象
编码string| Null default = null
标志string默认='r'
callback函数
该options.flag
看起来很有希望。 所以我们尝试
fs.writeFile(path, data, { flag: 'wx' }, function (err) { if (err) throw err; console.log("It's saved!"); });
它可以完美的写一个单一的。 我猜这个代码会以一些更奇怪的方式失败,如果你试图用它来解决你的任务。 你有一个习惯性的“检查a_#.jpg
存在,如果它是空的,写在那里”操作,但是所有其他的fs
状态都没有被locking,而a_1.jpg
文件可能自发地消失,而你已经检查a_5.jpg
。 大多数*文件系统不是ACID数据库,而且至less可以进行一些primefaces操作的事实是奇迹般的。 wx
代码很可能在某个平台上不起作用。 所以为了您的理智,最后使用数据库 。
一些更多的信息的痛苦
想象一下,我们正在写一些类似memoize-fs
caching文件系统函数调用的结果,以节省我们一些networking/ CPU时间。 如果存在,我们可以打开文件进行阅读,如果文件不存在,我们可以打开文件进行阅读吗? 让我们看看这些标志。 经过一段时间的脑力锻炼后,我们可以看到a+
是否符合我们的要求:如果文件不存在,它将创build一个文件并将其打开,以便读取和写入;如果文件存在,则不会清除文件w+
会)。 但是现在我们不能在(smth)File
使用它,也不能在create(Smth)Stream
函数中使用它。 这似乎是一个缺失的function。
因此,随意将它作为一个function请求(甚至是一个bug)提交给Node.js github,因为缺lessprimefacesasynchronous文件系统API是Node的一个缺点。 尽pipe不要期待很快的改变。
这里有一些选项:
1)有2个“fs”电话 。 第一个是“ fs.exists ”调用,第二个是“ fs.write / read”等。
//checks if the file exists. //If it does, it just calls back. //If it doesn't, then the file is created. function checkForFile(fileName,callback) { fs.exists(fileName, function (exists) { if(exists) { callback(); }else { fs.writeFile(fileName, {flag: 'wx'}, function (err, data) { callback(); }) } }); } function writeToFile() { checkForFile("file.dat",function() { //It is now safe to write/read to file.dat fs.readFile("file.dat", function (err,data) { //do stuff }); }); }
2)或先创build一个空文件 :
– – 同步:
//If you want to force the file to be empty then you want to use the 'w' flag: var fd = fs.openSync(filepath, 'w'); //That will truncate the file if it exists and create it if it doesn't. //Wrap it in an fs.closeSync call if you don't need the file descriptor it returns. fs.closeSync(fs.openSync(filepath, 'w'));
— ASync:
var fs = require("fs"); fs.open(path, "wx", function (err, fd) { // handle error fs.close(fd, function (err) { // handle error }); });
3)或使用“ 触摸 ”: https : //github.com/isaacs/node-touch
怎么样使用a
选项?
根据文件 :
'a +' – 打开文件进行阅读和追加。 如果该文件不存在,则会创build该文件。
它似乎与createWriteStream
完美的工作
在一次系统调用中就可以使用fs-extra
npm模块。 在此之后,文件将被创build以及它将被放置的目录。
const fs = require('fs-extra'); const file = '/tmp/this/path/does/not/exist/file.txt' fs.ensureFile(file, err => { console.log(err) // => null });
另一种方法是使用ensureFileSync这将做同样的事情,但同步。
const fs = require('fs-extra'); const file = '/tmp/this/path/does/not/exist/file.txt' fs.ensureFileSync(file)
你可以做这样的事情:
function writeFile(i){ var i = i || 0; var fileName = 'a_' + i + '.jpg'; fs.exists(fileName, function (exists) { if(exists){ writeFile(++i); } else { fs.writeFile(fileName); } }); }