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


Posted in NodeJs onOctober 17, 2018

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

需求

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

说干就干。

文件夹的路径如下所示:

一级路径:test
二级路径:A,B,C...共十三个文件夹
三级路径:每个二级路径下有3-8个文件夹不等
四级路径:a.jpg,b.jpg,c.jpg等数量不等的图片文件

思路

1.一个全局变量:数组类型obj。

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

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

3.依次重复步骤2,直至寻找到路径下的文件,将文件名name和拼合好的路径src放入归属的list中,如下:

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

实践

语言

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);
})();

提示

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

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

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

async.forEachLimit是异步串行函数,可以同批次运行指定数量的代码,可以避免一次遍历太多,里面的参数依次为(数组,指定的数量,执行函数,错误回调)。

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

//如果路径参数src里匹配到了obj中元素的name,说明数组里已经有了上级文件夹,则向此上级文件夹内插入此时的文件夹名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 {}
})

对我来说,这段代码是一段丑陋的函数,处理方法过于粗糙,并且占用了不必要的内存空间,更严重的是,拖累了整体文件的运行速度,但时间仓促,加之能力菜的真实,暂时还尚未想出解决方案。

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

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

//src是此时运行的search方法内的文件路径参数,对item.name也就是二级路径的文件名进行匹配,如果正确,则对三级路径下的文件名进行匹配(本来我想在这里写递归或者回调的,太懒取消原计划)。全部都匹配正确,则往内插入文件名和文件路径
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

这篇小笔记就结束了,这个轮子遇到的问题很浅显,但值得重视。对我将来写大型单页应用或是系统型网站非常有借鉴意义,所以此篇文章的漏洞和错误,我会再次进行排查,以达到最优的解决方法。我在这里抛砖引玉,诚恳希望各位同仁前辈能不吝赐教!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs爬虫抓取数据乱码问题总结
Jul 03 NodeJs
Nodejs如何搭建Web服务器
Mar 28 NodeJs
Nodejs学习item【入门手上】
May 05 NodeJs
图片上传之FileAPI与NodeJs
Jan 24 NodeJs
用Nodejs搭建服务器访问html、css、JS等静态资源文件
Apr 28 NodeJs
nodejs动态创建二维码的方法
Aug 12 NodeJs
nodejs更新package.json中的dependencies依赖到最新版本的方法
Oct 10 NodeJs
nodejs实现范围请求的实现代码
Oct 12 NodeJs
Nodejs让异步变成同步的方法
Mar 02 NodeJs
搭建一个nodejs脚手架的方法步骤
Jun 28 NodeJs
NodeJS开发人员常见五个错误理解
Oct 14 NodeJs
一文秒懂nodejs中的异步编程
Jan 28 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 #NodeJs
深入理解NodeJS 多进程和集群
Oct 17 #NodeJs
CentOS7中源码编译安装NodeJS的完整步骤
Oct 13 #NodeJs
NodeJS加密解密及node-rsa加密解密用法详解
Oct 12 #NodeJs
NodeJS使用Range请求实现下载功能的方法示例
Oct 12 #NodeJs
nodejs实现范围请求的实现代码
Oct 12 #NodeJs
NodeJS搭建HTTP服务器的实现步骤
Oct 12 #NodeJs
You might like
Laravel搭建后台登录系统步骤详解
2016/07/26 PHP
PHP自定义图片缩放函数实现等比例不失真缩放的方法
2016/08/19 PHP
php中简单的对称加密算法实现
2017/01/05 PHP
Laravel5.* 打印出执行的sql语句的方法
2017/07/24 PHP
tp5框架使用composer实现日志记录功能示例
2019/01/10 PHP
ext监听事件方法[初级篇]
2008/04/27 Javascript
jQuery 学习第七课 扩展jQuery的功能 插件开发
2010/05/17 Javascript
JavaScript中关于indexOf的使用方法与问题小结
2010/08/05 Javascript
JavaScript对IE操作的经典代码(推荐)
2014/03/10 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
2014/06/26 Javascript
node.js中的console用法总结
2014/12/15 Javascript
JQuery插件Quicksand实现超炫的动画洗牌效果
2015/05/03 Javascript
浅谈angular.js中实现双向绑定的方法$watch $digest $apply
2015/10/14 Javascript
详解JavaScript实现设计模式中的适配器模式的方法
2016/05/18 Javascript
Vee-validate 父组件获取子组件表单校验结果的实例代码
2019/05/20 Javascript
为vue项目自动设置请求状态的配置方法
2019/06/09 Javascript
JS实现的字符串数组去重功能小结
2019/06/17 Javascript
微信小程序动态显示项目倒计时
2019/06/20 Javascript
JavaScript实现alert弹框效果
2020/11/19 Javascript
在Python中使用Mako模版库的简单教程
2015/04/08 Python
详解Python Matplotlib解决绘图X轴值不按数组排序问题
2019/08/05 Python
Python 读取用户指令和格式化打印实现解析
2019/09/02 Python
Python实现平行坐标图的绘制(plotly)方式
2019/11/22 Python
python处理RSTP视频流过程解析
2020/01/11 Python
Python爬虫:Request Payload和Form Data的简单区别说明
2020/04/30 Python
pandas之分组groupby()的使用整理与总结
2020/06/18 Python
用Python实现职工信息管理系统
2020/12/30 Python
俄罗斯最大的灯具网站:Fandeco
2020/03/14 全球购物
华为慧通面试题
2012/09/11 面试题
室内设计自我鉴定
2013/10/15 职场文书
小松树教学反思
2014/02/11 职场文书
犯错检讨书
2014/02/21 职场文书
《美丽的丹顶鹤》教学反思
2014/04/22 职场文书
小学大队干部竞选稿
2015/11/20 职场文书
导游词之神仙居景区
2019/11/15 职场文书
CSS3 制作的悬停缩放特效
2021/04/13 HTML / CSS