NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法

 更新时间£º2018年10月17日 13:46:59   作者£º维伦   我要评论

这篇文章主要介绍了NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法£¬小编觉得挺不错的£¬现在分享给大家£¬也给大家做个参考¡£一起跟随小编过来看看吧

在编程之前£¬一定要有一个信条£º代码是为了减少工作量而生的£¬重复枯燥的工作是不能容忍的¡£

需求

这是由上篇文章衍生出的需求£¬我已经将一个文件夹内所有的文件名转译为英文£¬但我在页面上还需要将这些?#35745;?#24341;入加载¡£如果一个一个手写到程序里£¬未免有点劳心劳神¡£那么何不将这个文件夹按照存放路径变成一个相应的JSON在前端请求并渲染呢£¿

说干就干¡£

文件夹的路径如下所示£º

一级路径£ºtest
二级路径£ºA,B,C...共十三个文件夹
三级路径£º每个二级路径下有3-8个文件夹不等
四级路径£ºa.jpg,b.jpg,c.jpg等数量不等的?#35745;?#25991;件

思路

1.一个全局变量£º数组类型obj¡£

2.递归遍历目录£¬是文件夹的取出名字£¬建立一个对象£¬放入文件夹名name和一个空数组list£¬如

{
  name:'fileName',
  list:[]//用来存放下属路径
}

3.?#26469;?#37325;复步骤2£¬直至寻找到路径下的文件£¬将文件名name和拼合好的路径src放入归属的list中£¬如下£º

list:[
  {
    name:'fileName',
    src:'filePath'
  }
]

?#23548;?/strong>

语言

NodeJS

需求模块
fs/async¡£

代码 先上代码£¬逻辑解析在提示补上¡£

(function() {
 Array.prototype.distinct = function() {
 var arr = this,
  result = [],
  i,
  j,
  len = arr.length;
 for (i = 0; i < len; i++) {
  for (j = i + 1; j < len; j++) {
  if (arr[i].name === arr[j].name) {
   j = ++i;
  }
  }
  result.push(arr[i]);
 }
 return result;
 }
 // 主业务代码
 var fs = require("fs");
 var async = require('async');
 var obj = [];
 var search = function(src) {
 // 读取目录中的所有文件/目录
 fs.readdir(src, function(err, paths) {
  if (err) {
  throw err;
  }
  paths.forEach(function(path) {
  var _src = src + '/' + path;
  fs.stat(_src, function(err, st) {
   if (err) {
   throw err;
   }
   // 判断是否为文件
   if (st.isFile()) {
   async.forEachLimit(obj, 1000, function(item, callback) {
    if (src.match(new RegExp(item.name))) {

    item.list.forEach(function(iv) {
     if (src.match(new RegExp(iv.name))) {
     iv.list.push({
      name: path.split('.')[0],
      src: _src
     })

     }

    })
    }
    callback(null, item)
   })
   obj = obj.distinct();
   fs.writeFile("main.json", JSON.stringify(obj), "utf-8", (error) => {
    //监听错误£¬如正常输出£¬则打印null
    if (error == null) {
    obj = null;

    }

   });
   }
   // 如果是目录则递归调用自身
   else if (st.isDirectory()) {
   if (obj.length <= 0) {
    obj.push({
    name: path,
    list: []
    })
   } else {
    var value = paths;
    async.forEachLimit(obj, 1000, function(item, callback) {
    //如果数组里已有
    if (src.match(new RegExp(item.name))) {
     item.list.push({
     name: path,
     list: []
     })
    } else {
     value.forEach(function(vv) {
     if (vv == item.name) {
      obj.push({
      name: path,
      list: []
      })
     } else {}
     })
    }
    callback(null, item)
    }, function(err) {
    if (err) throw err;
    })
   }
   exists(_src, search);

   }
  });
  });
 });
 };
 var exists = function(src, callback) {
 callback(src);
 };
 exists('./test2', search);
})();

提示

首先£¬要有心理准备£¬这个轮子里使用了递归+很多遍历£¬这对于内存占用是很?#29616;?#30340;£¬尤其是我们还有一个 全局变量OBJ £¬如果逻辑处理不好很容易会出现错误内存溢出¡£这也是为什么我引入了async模块的理由¡£

在引入模块之后£¬第一步要着眼于判断为文件夹后的函数£º

//如果obj为空£¬?#24471;?#25105;们是第一次进入函数£¬那么插入一个新的元素
if (obj.length <= 0) {
 obj.push({
 name: path,
 list: []
 })
}

async.forEachLimit是异步串行函数£¬可以同批次运行指定数量的代码£¬可以避免一次遍历太多£¬里面的参数?#26469;?#20026;£¨数组£¬指定的数量£¬执行函数£¬错误回调£©¡£

下面代码中的参数很多£¬如paths£¬path£¬src£¬_src等£¬打代码的时候经常会让我头脑不清晰£¬这也侧面告诫了我一个问题£¬同一作用域内不宜有太多处理函数¡£

//如果路径参数src里匹配到了obj中元素的name£¬?#24471;?#25968;组里已经有了上级文件夹£¬则向此上级文件夹内插入此时的文件夹名path
if (src.match(new RegExp(item.name))) {
 item.list.push({
 name: path,
 list: []
 })
} 

/*如果没有上级文件夹£¬那往尾部插入新的元素
 *进行一次遍历排查£¬去除掉二级路径向尾部插入的举动*/

value.forEach(function(vv) {
 if (vv == item.name) {
 obj.push({
  name: path,
  list: []
 })
 } else {}
})

对我来说£¬这段代码是一段丑陋的函数£¬处理方法过于粗糙£¬并且占用了不必要的内存空间£¬更?#29616;?#30340;是£¬拖累了整体文件的运行速度£¬但时间?#25191;Ù£?#21152;之能力菜的真实£¬暂时还尚未想出解决方案¡£

还要备注的是£¬这里本来想达到的去重判断因为上级方法套用的遍历次序不同£¬造成我只完成了初级的防止push重复£¬却又有了递归式的重?#30784;?#26377;兴趣的朋友在使用这个demo时可以将首行的去重方法删除£¬看看效果¡£

处理好了文件夹状态下的方法£¬来看看已经到了四级路径的处理

//src是此时运行的search方法内的文件路径参数£¬对item.name也就是二级路径的文件名进行匹配£¬如果正确£¬则对三级路径下的文件名进行匹配£¨本来我想在这里写递归或者回调的£¬太懒取消原计划£©¡£全部?#35745;?#37197;正确£¬则往内插入文件名和文件路径
async.forEachLimit(obj, 1000, function(item, callback) {
 if (src.match(new RegExp(item.name))) {
 item.list.forEach(function(iv) {
  if (src.match(new RegExp(iv.name))) {
  iv.list.push({
   name: path.split('.')[0],
   src: _src
  })
  }
 })
 }
 callback(null, item)
})

函数到这里时£¬就是最后一步£¬写入json文件了£¬不能忘记的是£¬这里需要进行一次去重£¬原因在上文提到了£¬方法在函数行首¡£

PS£º在运行结束之后£¬一定要将全局变量清空£¬虽然我暂时尚未遇到因此理由内存的崩溃£¬但可以预见到的是£¬在用于庞大文件夹时£¬势必会对内存有很大的伤害¡£

obj = obj.distinct();
fs.writeFile("main.json", JSON.stringify(obj), "utf-8", (error) => {
 //监听错误£¬如正常输出£¬则打印null
 if (error == null) {
 obj = null;
 }
});

END

这篇小?#22987;?#23601;结束了£¬这个轮子遇到的问题很浅显£¬但值得重?#21360;?#23545;我将来写大型单页应用或是系统型网站非常有借鉴意义£¬所?#28304;?#31687;文章的漏洞和错误£¬?#19968;?#20877;次进?#20449;?#26597;£¬?#28304;?#21040;最优的解决方法¡£我在这里抛砖引玉£¬诚恳希望各位同仁前辈能不吝赐教£¡

以上就是本文的全部内容£¬希望对大家的学习有所帮助£¬也希望大家多多支持脚本之家¡£

相关文章

  • Node.js巧妙实现Web应用代码热更新

    Node.js巧妙实现Web应用代码热更新

    本文给大家?#27493;?#30340;是Node.js的代码热更新的问题£¬其主要实现原理 是怎么对 module 对象做处理,也就是手工监听文件修改, 然后清楚模块缓存, 重新挂载模块£¬思路清晰考虑细致, 虽然有点冗余代码,但还是推荐给大家
    2015-10-10
  • 最新评论

    常用在线小工具

    ÁÉÄþ35Ñ¡7¿ª½±½á¹û