今天我們主要來介紹下Node體系中的文件系統。
代碼示例:
const fs = require('fs'); const assert = require('assert'); const fd = fs.openSync('./file.txt', 'w '); const writeBuf = new Buffer('some data to write'); fs.writeSync(fd, writeBuf, 0, writeBuf.length, 0); const readBuf = new Buffer(writeBuf.length); fs.readSync(fd, readBuf, 0, writeBuf.length, 0); assert.equal(writeBuf.toString(), readBuf.toString()); fs.closeSync(fd);
讀寫流const fs = require('fs'); const readable = fs.createReadStream('./original.txt'); const writeable = fs.createWriteStream('./copy.txt'); readable.pipe(writeable);
文件監控fs.watchFile 比 fs.watch 低效,但更好用。
同步讀取與 require同步 fs 的方法應該在第一次初始化應用的時候使用。
const fs = require('fs'); const config = JSON.parse(fs.readFileSync('./config.json').toString()); init(config);
require:
const config = require('./config.json); init(config);
文件描述是在操作系統中管理的在進程中打開文件所關聯的一些數字或者索引。操作系統通過指派一個唯一的整數給每個打開的文件用來查看關于這個文件。
console.log('log') 是 process.stdout.write('log') 的語法糖。
一個文件描述是 open 以及 openSync 方法調用返回的一個數字
const fd = fs.openSync('myfile', 'a'); console.log(typeof fd === 'number'); // true
文件鎖協同多個進程同時訪問一個文件,保證文件的完整性以及數據不能丢失:
Node 實現鎖文件
獨占标記
// 所有需要打開文件的方法,fs.writeFile、fs.createWriteStream、fs.open 都有一個 x 标記 // 這個文件應該已獨占打開,若這個文件存在,文件不能被打開 fs.open('config.lock', 'wx', (err) => { if (err) { return console.err(err); } }); // 最好将當前進程号寫進文件鎖中 // 當有異常的時候就知道最後這個鎖的進程 fs.writeFile( 'config.lock', process.pid, { flogs: 'wx' }, (err) => { if (err) { return console.error(err) }; }, );
mkdir 文件鎖
獨占标記有個問題,可能有些系統不能識别 0_EXCL 标記。另一個方案是把鎖文件換成一個目錄,PID 可以寫入目錄中的一個文件。
fs.mkidr('config.lock', (err) => { if (err) { return console.error(err); } fs.writeFile(`/config.lock/${process.pid}`, (err) => { if (err) { return console.error(err); } }); });
lock 模塊實現
const fs = require('fs'); const lockDir = 'config.lock'; let hasLock = false; exports.lock = function (cb) { // 獲取鎖 if (hasLock) { return cb(); } // 已經獲取了一個鎖 fs.mkdir(lockDir, function (err) { if (err) { return cb(err); } // 無法創建鎖 fs.writeFile(lockDir '/' process.pid, function (err) { // 把 PID寫入到目錄中以便調試 if (err) { console.error(err); } // 無法寫入 PID,繼續運行 hasLock = true; // 鎖創建了 return cb(); }); }); }; exports.unlock = function (cb) { // 解鎖方法 if (!hasLock) { return cb(); } // 如果沒有需要解開的鎖 fs.unlink(lockDir '/' process.pid, function (err) { if (err) { return cb(err); } fs.rmdir(lockDir, function (err) { if (err) return cb(err); hasLock = false; cb(); }); }); }; process.on('exit', function () { if (hasLock) { fs.unlinkSync(lockDir '/' process.pid); // 如果還有鎖,在退出之前同步删除掉 fs.rmdirSync(lockDir); console.log('removed lock'); } });
遞歸文件操作推薦一個線上庫:mkdirp
遞歸:要解決我們的問題就要先解決更小的相同的問題。
dir-a ├── dir-b │ ├── dir-c │ │ ├── dir-d │ │ │ └── file-e.png │ │ └── file-e.png │ ├── file-c.js │ └── file-d.txt ├── file-a.js └── file-b.txt
查找模塊:find /asset/dir-a -name="file.*"
[ 'dir-a/dir-b/dir-c/dir-d/file-e.png', 'dir-a/dir-b/dir-c/file-e.png', 'dir-a/dir-b/file-c.js', 'dir-a/dir-b/file-d.txt', 'dir-a/file-a.js', 'dir-a/file-b.txt', ] const fs = require('fs'); const join = require('path').join; // 同步查找 exports.findSync = function (nameRe, startPath) { const results = []; function finder(path) { const files = fs.readdirSync(path); for (let i = 0; i < files.length; i ) { const fpath = join(path, files[i]); const stats = fs.statSync(fpath); if (stats.isDirectory()) { finder(fpath); } if (stats.isFile() && nameRe.test(files[i])) { results.push(fpath); } } } finder(startPath); return results; }; // 異步查找 exports.find = function (nameRe, startPath, cb) { // cb 可以傳入 console.log,靈活 const results = []; let asyncOps = 0; // 2 function finder(path) { asyncOps ; fs.readdir(path, function (er, files) { if (er) { return cb(er); } files.forEach(function (file) { const fpath = join(path, file); asyncOps ; fs.stat(fpath, function (er, stats) { if (er) { return cb(er); } if (stats.isDirectory()) finder(fpath); if (stats.isFile() && nameRe.test(file)) { results.push(fpath); } asyncOps--; if (asyncOps == 0) { cb(null, results); } }); }); asyncOps--; if (asyncOps == 0) { cb(null, results); } }); } finder(startPath); }; console.log(exports.findSync(/file.*/, `${__dirname}/dir-a`)); console.log(exports.find(/file.*/, `${__dirname}/dir-a`, console.log));
監視文件和文件夾想要監聽一個文件或者目錄,并在文件更改後執行一個動作。
const fs = require('fs'); fs.watch('./watchdir', console.log); // 穩定且快 fs.watchFile('./watchdir', console.log); // 跨平台
逐行地讀取文件流const fs = require('fs'); const readline = require('readline'); const rl = readline.createInterface({ input: fs.createReadStream('/etc/hosts'), crlfDelay: Infinity }); rl.on('line', (line) => { console.log(`cc ${line}`); const extract = line.match(/(\d \.\d \.\d \.\d ) (.*)/); });
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!