UNPKG

jbd

Version:
340 lines (301 loc) 8.63 kB
/** * ========================================== * Name: FS * Author: Buddy-Deus * CreTime: 2016-02-16 * Description: 基础文件操作 * Log * 2016-02-16 初始化 * ========================================== */ jBD.define(function (module, exports, require) { "use strict"; let API; const fs = require("fs"), path = require("path"), txtFileType = [".txt", ".json", ".ini", ".js", ".css", ".html", ".md"], encodeType = ["ascii", "utf8", "utf16le"]; const fmtPath = value => value.trim().replace(/\\/g, "/"), isTXT = value => jBD.has(path.extname(value).toLowerCase(), txtFileType), listDir = (src, callback) => { let list = fs.readdirSync(src), state = true, count = 0; for (let i = 0, o; i < list.length; i++) { if (!state) return; count++; o = path.join(src, list[i]); if (callback(list[i], o, fs.statSync(o)) === false) break; } return count; }, operFile_TXT = (src, dest, callback, move, encoding, sync) => { if (sync) { try { fs.writeFileSync(dest, fs.readFileSync(src, encoding), encoding); if (callback) callback("end", src, dest); if (move) fs.unlinkSync(src); } catch (e) { if (callback) callback("error", src, dest, e); } } else { fs.writeFile(dest, fs.readFileSync(src, encoding), encoding, err => { if (callback) callback(err ? "error" : "end", src, dest, err); if (!err && move) fs.unlinkSync(src); }); } }, operFile_Stream = (src, dest, callback, move) => { let rs = fs.createReadStream(src), ws = fs.createWriteStream(dest); ws.on("end", () => { ws.end(); if (callback) callback("end", src, dest); if (move) fs.unlinkSync(src); }); if (!callback) rs.pipe(ws); else { rs.pipe(require('stream').Transform({ transform: function (buf, enc, next) { if (callback) callback("data", src, dest); next(null, buf); } })).pipe(ws); } }, operFile = (src, dest, opt, callback) => { API.Make(dest, true); if (!opt.stream && isTXT(src)) operFile_TXT(src, dest, callback, opt.move, opt.encoding, opt.sync); else operFile_Stream(src, dest, callback, opt.move); }, operDir = (src, dest, opt, callback) => { opt.count = listDir(src, (f, p, o) => { if (o.isDirectory()) operDir(path.join(src, f), path.join(dest, f), opt, callback); else operFile(path.join(src, f), path.join(dest, f), { sync: true, stream: opt.stream, encoding: opt.encoding, move: opt.move }, callback) }); if (opt.empty && opt.count == 0) API.Make(dest); }; API = { /** * 列表目录 * 当 deep=true && show=1 时,列出此目录下所有文件(包含子目录) * * @param {string} src * @param {object|boolean} opt * @param {boolean} [opt.deep=false] 是否搜索子目录 * @param {boolean|number} [opt.show=0] 过滤方式 * @param {function} callback * @returns {Array} */ List: (src, opt = {}, callback = opt) => { let result = [], { deep, show } = opt; switch (typeof (opt)) { case "boolean": deep = opt; break; case "number": case "string": show = opt; break; } deep = deep === true; switch (String(show)) { default: show = 0; break; case "1": case "file": case "true": show = 1; break; case "2": case "dir": case "false": show = 2; break; } if (!jBD.isFunction(callback)) callback = null; if (!fs.existsSync(src)) return result; listDir(src, (f, p, o, l) => { o = {name: f, path: p, state: o, dir: o.isDirectory()}; l = result.length; result.push(o); if (o.dir) { if (deep) { Array.prototype.push( show == 1 ? result : (o.child = []), API.List( o.path, { deep: true, show: show }, callback) ); } else if (show == 1) result.pop(); } else if (show == 2) result.pop(); if (l == result.length) return; if (callback && callback(o.name, o.path, o.dir, o.state) === false) return false; }); return result; }, /** * 创建目录 * * @param {string} src * @param {boolean} [file=false] * @returns {string} */ Make: (src, file = false) => { src = fmtPath(src); file = file === true; let dest = src; if (fs.existsSync(dest)) return dest; for (let i = 0, c = file ? 1 : 0, l = dest.split("/"), o = ""; i < l.length - c; i++) { if (i == 0) o = l[0] || "/"; else if (l[i] && !fs.existsSync(o = path.join(o, l[i]))) fs.mkdirSync(o); dest = o; } return dest; }, /** * 删除目录 * * @param {string} dest * @param {boolean} [self=true] 是否删除自身 * @returns {boolean} */ Remove: (dest, self = true) => { dest = fmtPath(dest); self = self !== false; if (!fs.existsSync(dest)) return false; if (fs.statSync(dest).isFile()) fs.unlinkSync(dest); else { listDir(dest, (f, p, o) => { if (o.isDirectory()) API.Remove(p, true); else fs.unlinkSync(p); }); if (self) fs.rmdirSync(dest); } return true; }, /** * 操作目录/文件 (移动/复制) * * @param {string} src * @param {string} dest * @param {object} [opt] * @param {boolean} [opt.stream=false] 是否启用文件流,否则作为自动识别 * @param {boolean} [opt.sync=false] 是否异步方式 * @param {string} [opt.encoding=utf8] 编码格式 * @param {boolean} [opt.empty=true] 是否创建空目录 * @param {boolean} [opt.move=false] 是否移动 * @param {function} [callback] */ Oper: (src, dest, opt = {}, callback = opt) => { if (!fs.existsSync(src)) return; let {sync, stream, encoding, empty, move} = opt; switch (typeof(opt)) { case "string": encoding = opt; break; case "boolean": move = opt; break; } sync = sync === true; stream = stream === false; if (!jBD.has(encoding, encodeType)) encoding = encodeType[0]; empty = empty !== false; move = move === true; opt = {sync, stream, encoding, empty, move}; callback = ((func, rm) => { return (tag, src, dest) => { if (func) func(tag, src, dest); if (tag == "end" && rm) rm(src); }; })(jBD.isFunction(callback) ? callback : null, opt.move ? API.Remove : null); if (fs.statSync(src).isDirectory()) operDir(src, dest, opt, callback); else operFile(src, dest, opt, callback); }, /** * 打开文件 * * @param {string} src * @param {object} [opt] * @param {string} [opt.encoding=utf8] 编码方式 * @param {boolean} [opt.obj=true] 是否建立对象 * @returns {buffer|object|string} */ Load: (src, opt = {}) => { if (!fs.existsSync(src)) return null; let txt = isTXT(src), { encoding, obj } = opt, result; switch (typeof(opt)) { case "boolean": obj = opt; break; case "string": encoding = opt; break; } obj = obj !== false; encoding = txt ? (jBD.has(encoding, encodeType) ? encoding : "utf8") : null; result = fs.readFileSync(src, encoding); if (txt) { result = result.toString(); if (obj) result = jBD.Conver.toJSON(result); } return result; }, /** * 保存文件 * * @param {string} dest * @param {buffer|Uint8Array|object|string} [opt] * @param {buffer|Uint8Array|object|string} [opt.data=''] * @param {boolean} [opt.write=true] 覆盖全部内容 * @param {string} [opt.encoding=utf8] * @constructor */ Save: (dest, opt = {}) => { let {data, write, encoding} = opt; switch (typeof(opt)) { case "object": if (opt instanceof Buffer) data = opt; else if (opt instanceof Uint8Array) data = opt; break; case "string": data = opt; break; case "boolean": write = opt; break; } if (!data && typeof(data) != "number") data = ""; else if (!(data instanceof Buffer || data instanceof Uint8Array)) data = jBD.Conver.toString(data); write = write !== false; if (!jBD.has(encoding, encodeType)) encoding = "utf8"; API.Make(dest, true); fs[write ? "writeFileSync" : "appendFileSync"](dest, data, {encoding: encoding}); } }; return API; }, {module: module, exports: this}, ["Conver"], "FS");