Node.js'de Dosyaya Yazarken Dizin Oluştur


135

Node.js ile uğraşıyorum ve küçük bir sorun buldum. Adlı dizinde bulunan bir komut dosyam var data. Komut dosyasının, alt dizindeki bir alt dizindeki bir dosyaya bazı veriler yazmasını istiyorum data. Ancak şu hatayı alıyorum:

{ [Error: ENOENT, open 'D:\data\tmp\test.txt'] errno: 34, code: 'ENOENT', path: 'D:\\data\\tmp\\test.txt' }

Kod aşağıdaki gibidir:

var fs = require('fs');
fs.writeFile("tmp/test.txt", "Hey there!", function(err) {
    if(err) {
        console.log(err);
    } else {
        console.log("The file was saved!");
    }
}); 

Bir dosyaya yazmak için çıkmazsa, Node.js'nin dizin yapısını oluşturmasını nasıl sağlayacağımı öğrenmeme yardımcı olan var mı?


1
fs.promises.mkdir(path.dirname("tmp/test.txt"), {recursive: true}).then(x => fs.promises.writeFile("tmp/test.txt", "Hey there!"))
Offenso

Yanıtlar:


127

Düğüm> 10.12.0

fs.mkdir artık { recursive: true }böyle bir seçeneği kabul ediyor :

// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});

veya bir sözle:

fs.promises.mkdir('/tmp/a/apple', { recursive: true }).catch(console.error);

Düğüm <= 10.11.0

Bunu mkdirp veya fs-extra gibi bir paketle çözebilirsiniz . Bir paket kurmak istemiyorsanız, lütfen aşağıdaki Tiago Peres França'nın cevabına bakın.


4
Benim gideceğim şey bu ... bu istatistikler beni kazandı.
Aran Mulholland

bunun fs.promiseshala deneysel nodejs.org/dist/latest-v10.x/docs/api/…
lasec0203

132

Herhangi bir ek paket kullanmak istemiyorsanız, dosyanızı oluşturmadan önce aşağıdaki işlevi çağırabilirsiniz:

var path = require('path'),
    fs = require('fs');

function ensureDirectoryExistence(filePath) {
  var dirname = path.dirname(filePath);
  if (fs.existsSync(dirname)) {
    return true;
  }
  ensureDirectoryExistence(dirname);
  fs.mkdirSync(dirname);
}

2
Bunun statSyncyerine stackoverflow.com/questions/4482686/… 'yeexistsSync dayalı olarak kullanılmalıdır
GavinR

1
pathaynı zamanda şu şekilde gerekli olması gereken bir pakettir fs: var path = require('path')Herhangi birinin merak etmesi durumunda. Düğüm belgelerine bakın .
Rafael Emshoff

9
fs.existsSyncolduğu değil kaldırılan , sadece fs.existsolduğunu.
zzzzBov

6
Fs.existsSync işlevinin kullanımdan kaldırılıp kaldırılmadığı konusunda bazı karışıklıklar var. İlk başta, anladığım kadarıyla öyle olduğunu düşündüm, bu yüzden cevabı bunu yansıtacak şekilde güncelledim. Ancak şimdi, @zzzzBov'un işaret ettiği gibi, dokümantasyon sadece fs.exists'in kullanımdan kaldırıldığını, fs.existsSync'in kullanımının hala geçerli olduğunu açıkça belirtiyor. Bu nedenle önceki kodu sildim ve cevabım artık sadece daha basit çözümü içeriyor (fs.existsSync kullanımıyla).
Tiago Peres França

1
@chrismarx şu yolu hayal edin: "/home/documents/a/b/c/myfile.txt". "/ ev / belgeler" var, önündeki her şey yok. "SureDirectoryExistence" ilk kez çağrıldığında, dizin adı "/ home / belgeler / a / b / c" olur. Şu anda fs.mkdirSync'i (dizin adı) çağıramıyorum çünkü "/ ev / belgeler / a / b" de mevcut değil. "C" dizinini oluşturmak için, önce "/ home / dokümanlar / a / b" nin varlığından emin olmam gerekiyor.
Tiago Peres França

43

İle düğüm-fs-ekstra kolayca yapabilirsiniz.

Yükle

npm install --save fs-extra

Ardından outputFileyöntemi kullanın . Belgeleri şöyle diyor:

WriteFile ile hemen hemen aynıdır (yani üzerine yazar), tek fark, eğer ana dizin yoksa, oluşturulur.

Üç şekilde kullanabilirsiniz:

Geri arama stili

const fse = require('fs-extra');

fse.outputFile('tmp/test.txt', 'Hey there!', err => {
  if(err) {
    console.log(err);
  } else {
    console.log('The file was saved!');
  }
})

Sözleri Kullanmak

Sözleri kullanırsanız ve umarım kod budur:

fse.outputFile('tmp/test.txt', 'Hey there!')
   .then(() => {
       console.log('The file was saved!');
   })
   .catch(err => {
       console.error(err)
   });

Senkronizasyon sürümü

Bir senkronizasyon sürümü istiyorsanız, sadece şu kodu kullanın:

fse.outputFileSync('tmp/test.txt', 'Hey there!')

Tam bir referans için, outputFilebelgeleri ve tüm node-fs-extra desteklenen yöntemleri kontrol edin .


26

Utanmaz fiş uyarısı!

İstediğiniz yol yapısındaki her dizini kontrol etmeniz ve yoksa manuel olarak oluşturmanız gerekecektir. Bunu yapmak için tüm araçlar zaten Node'un fs modülünde mevcuttur, ancak bunların hepsini mkpath modülümle yapabilirsiniz: https://github.com/jrajav/mkpath


1
bu, dosyayı doğrudan mı yoksa sadece dizin yapısını mı oluşturacak? Dosyayı oluştururken dizin yapısıyla birlikte dosyayı oluşturan bir çözüm arıyorum.
Hirvesh

Sadece dizin yapısı. Önce mkdir / yolunu yazarsınız ve herhangi bir hata yoksa dosyanızı yazmaya devam edin. Bir dosyaya tam yol verildiğinde, her ikisini de aynı anda yapacak bir işlev yazmak yeterince basit olacaktır - sadece dosya adını
yol.basename

1
Aslında o kadar basitti ki 2 dakikada yazdım . :) (Test edilmemiş)
jrajav

Güncelleme: Test edildi ve düzenlendi, ilk seferde işe yaramadıysa lütfen tekrar deneyin.
jrajav

8
@Kiyura Bunun yaygın olarak kullanılan mkdirp'ten farkı nedir?
David Weldon

9

Henüz yorum yapamadığım için, @ tiago-peres-frança fantastik çözüme dayalı gelişmiş bir cevap gönderiyorum (teşekkürler!). Yolda yalnızca son dizinin eksik olduğu bir durumda kodu dizin oluşturmaz, örneğin giriş "C: / test / abc" ve "C: / test" zaten mevcut. İşte çalışan bir snippet:

function mkdirp(filepath) {
    var dirname = path.dirname(filepath);

    if (!fs.existsSync(dirname)) {
        mkdirp(dirname);
    }

    fs.mkdirSync(filepath);
}

1
Bunun nedeni, @ tiago'nun çözümünün bir dosya yolu beklemesidir . Sizin durumunuzda, abcbir dizin oluşturmanız gereken dosya olarak yorumlanır. Ayrıca abcdizini oluşturmak için yolunuza bir kukla dosya ekleyin, örn C:/test/abc/dummy.txt.
Sphinxxx

Yinelemeli kullanın:fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso

1
@Offenso en iyi çözümdür, ancak yalnızca Node.js sürüm 10.12 ve üzeri için.
Nickensoul

8

Tavsiyem: Birkaç satır kodla kolayca yapabildiğiniz zaman bağımlılıklara güvenmemeye çalışın

İşte 14 satır kodda başarmaya çalıştığınız şey :

fs.isDir = function(dpath) {
    try {
        return fs.lstatSync(dpath).isDirectory();
    } catch(e) {
        return false;
    }
};
fs.mkdirp = function(dirname) {
    dirname = path.normalize(dirname).split(path.sep);
    dirname.forEach((sdir,index)=>{
        var pathInQuestion = dirname.slice(0,index+1).join(path.sep);
        if((!fs.isDir(pathInQuestion)) && pathInQuestion) fs.mkdirSync(pathInQuestion);
    });
};

1
Üçüncü satır böyle daha iyi olmaz mıydı? return fs.lstatSync(dpath).isDirectory(), aksi takdirde isDirectory () false döndürürse ne olur?
Giorgio Aresu

2
Yinelemeli kullanın:fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso

1
@Offenso 8 numaralı düğüm tarafından desteklenmiyor
Ievgen Naida

2

Bu modülü yeni yayınladım çünkü bu işlevselliğe ihtiyacım vardı.

https://www.npmjs.org/package/filendir

Node.js fs yöntemleri etrafında bir sarmalayıcı gibi çalışır. Bunu tam olarak aynı şekilde kullanabilirsiniz Yani alacağınız fs.writeFileve fs.writeFileSync(zaman uyumsuz ve uyumlu yazma ikisi)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.