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

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

需求前端

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

说干就干。面试

文件夹的路径以下所示:编程

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

思路bootstrap

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

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

?
1
2
3
4
{
   name: 'fileName' ,
   list:[] //用来存放下属路径
}

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

?
1
2
3
4
5
6
list:[
   {
     name: 'fileName' ,
     src: 'filePath'
   }
]

实践

语言

NodeJS

需求模块
fs/async。

代码 先上代码,逻辑解析在提示补上。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
( 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模块的理由。

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

?
1
2
3
4
5
6
7
//若是obj为空,说明咱们是第一次进入函数,那么插入一个新的元素
if (obj.length <= 0) {
  obj.push({
  name: path,
  list: []
  })
}

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//若是路径参数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时能够将首行的去重方法删除,看看效果。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//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:在运行结束以后,必定要将全局变量清空,虽然我暂时还没有遇到所以理由内存的崩溃,但能够预见到的是,在用于庞大文件夹时,势必会对内存有很大的伤害。

?
1
2
3
4
5
6
7
obj = obj.distinct();
fs.writeFile( "main.json" , JSON.stringify(obj), "utf-8" , (error) => {
  //监听错误,如正常输出,则打印null
  if (error == null ) {
  obj = null ;
  }
});
 
 
 
手把手从零打造企业级电商平台 – 前端实战 attach_img  ...2
React Native快速开发 厕所在哪App LBS定位 框架封装-某课网价值128元实战教程 attach_img
12套bootstrap精简课程合辑 attach_img
Vue2.0+Node.js+MongoDB全栈打造商城系统-某课网价值348元实战教程 attach_img  ...2
React.js入门基础与案例开发-某课网价值199元实战教程 attach_img  ...2
响应式开发一招致胜-某课网价值128元实战教程 attach_img  ...2
前端JavaScript面试技巧-某课网价值149元实战教程 attach_img  ...2
Bootstrap培训视频教程+Bootstrap实例教学 Bootstrap Web框架培训视频教程 attach_img
2017全新版零基础HTML视频教程 后盾网零基础学习HTML视频教程 2017后盾网最新版 attach_img
Jquery前端框架实战 JS经典实例32篇 BootStrap前端框架 云之梦实战学习前端开发技术 attach_img
了不得的NodeJS pdf电子书下载 attach_img
EasyUI极速入门视频教程 BTBOYS社区讲师孙宇老师EasyUI视频教程 attach_img
Web前端开发技术实战视频教程 初级入门+高级实战++专家课程+面试指导 极客学院 attach_img
2017最新版DIV+CSS视频教程 后盾网DIV+CSS入门精讲课程30集培训视频教程 attach_img
爱创课堂张容铭老师web前端精华培训课程+零基础Web前端开发工程师高端培训 attach_img
ReactJS基础视频教程 14课 附源码课件 attach_img
三套jQuery Mobile移动系列视频教程
麦子学院商城项目前端整站项目实战,附源码 attach_img
Vue 2.0高级实战开发移动端音乐WebApp–慕课网实战教程 attach_img
珠峰Node.js全栈开发 attach_img  ...2
相关文章
相关标签/搜索