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为什么选择javascript为载体语言
Jan 13 NodeJs
nodejs 整合kindEditor实现图片上传
Feb 03 NodeJs
nodejs开发微博实例
Mar 25 NodeJs
nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证示例
Dec 30 NodeJs
用nodejs搭建websocket服务器
Jan 23 NodeJs
nodejs爬虫遇到的乱码问题汇总
Apr 07 NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 NodeJs
NodeJS加密解密及node-rsa加密解密用法详解
Oct 12 NodeJs
详解nodejs 开发企业微信第三方应用入门教程
Mar 12 NodeJs
nodejs搭建本地服务器并访问文件操作示例
May 11 NodeJs
纯异步nodejs文件夹(目录)复制功能
Sep 03 NodeJs
nodejs对mongodb数据库的增加修删该查实例代码
Jan 05 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
php字符串分割函数explode的实例代码
2013/02/07 PHP
ThinkPHP之R方法实例详解
2014/06/20 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
2018/06/14 PHP
js的event详解。
2006/09/06 Javascript
Javascript 生成指定范围数值随机数
2009/01/09 Javascript
js 幻灯片的实现
2011/12/06 Javascript
jQuery JSON实现无刷新三级联动实例探讨
2013/05/28 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
js弹出确认是否删除对话框
2014/03/27 Javascript
JS数组的遍历方式for循环与for...in
2014/07/31 Javascript
jquery基础知识第一讲之认识jquery
2016/03/17 Javascript
AngularJS基础 ng-show 指令简单示例
2016/08/03 Javascript
AngularJS入门教程之AngularJS 模板
2016/08/18 Javascript
canvas实现手机端用来上传用户头像的代码
2016/10/20 Javascript
xmlplus组件设计系列之分隔框(DividedBox)(8)
2017/05/02 Javascript
详解使用nvm安装node.js
2017/07/18 Javascript
如何实现小程序tab栏下划线动画效果
2019/05/18 Javascript
对layui初始化列表的CheckBox属性详解
2019/09/13 Javascript
[06:45]DOTA2-DPC中国联赛 正赛 Magma vs LBZS 选手采访
2021/03/11 DOTA
python开发之thread实现布朗运动的方法
2015/11/11 Python
python实现二叉查找树实例代码
2018/02/08 Python
余弦相似性计算及python代码实现过程解析
2019/09/18 Python
python自动分箱,计算woe,iv的实例代码
2019/11/22 Python
Pytorch释放显存占用方式
2020/01/13 Python
python使用信号量动态更新配置文件的操作
2020/04/01 Python
python读取图片颜色值并生成excel像素画的方法实例
2021/02/19 Python
业务部经理岗位职责
2014/01/04 职场文书
竞选班干部演讲稿
2014/04/24 职场文书
兴趣小组活动总结
2014/05/05 职场文书
个人政风行风自查自纠报告
2014/10/21 职场文书
护士年终个人总结
2015/02/13 职场文书
《牧场之国》教学反思
2016/02/22 职场文书
2019银行竞聘书
2019/06/21 职场文书
各类场合主持词开场白范文集锦
2019/08/16 职场文书
pytorch 使用半精度模型部署的操作
2021/05/24 Python
Python安装使用Scrapy框架
2022/04/12 Python