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

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

需求

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

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

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

(0)

相关推荐

  • nodejs读取本地中文json文件出现乱码解决方法

    1. 确定json文件是UTF-8 无BOM编码的的.如果有BOM,会在读取第一行的时候出现乱码. Per "fs.readFileSync(filename, 'utf8') doesn't strip BOM markers #1918", fs.readFile is working as designed: BOM is not stripped from the header of the UTF-8 file, if it exists. It at the discret

  • Node.js返回JSONP详解

    在使用JQuery的Ajax从服务器请求数据或者向服务器发送数据时常常会遇到跨域无法请求的错误,常用的解决办法就是在Ajax中使用JSONP.基于安全性考虑,浏览器会存在同源策略,然而<script/>标签却具有跨域访问数据的能力,这就是JSONP工作的基本原理.有关同源策略以及什么是JSONP. 在Node.js中实现JSONP非常简单,通过下面的代码我们从服务器返回并运行一个JavaScript函数,这个JavaScript函数已经在调用方提前被定义好了,于是当它被返回的时候就自动执行了.

  • node.js中的buffer.toJSON方法使用说明

    方法说明: 将buffer对象 转换成json格式. 语法: 复制代码 代码如下: buffer.toJSON() 接收参数: 无 例子: 复制代码 代码如下: var buf = new Buffer('test'); var json = JSON.stringify(buf); console.log(json); // '{"type":"Buffer","data":[116,101,115,116]}' var copy = JSON

  • Node.js JSON模块用法实例分析

    本文实例讲述了Node.js JSON模块用法.分享给大家供大家参考,具体如下: 一.JSON.stringify语法: JSON.stringify(value [, replacer] [, space]) value:是必选字段.就是你输入的对象,比如数组,类等. replacer(可选参数):它又分为2种方式,一种是数组,第二种是方法. (1)replacer为数组时,表示的是Key,只有在类中有出现过的Key的键值对(Key-Value)才会在转化的结果中出现. replacer数组仅

  • 借助node实战JSONP跨域实例

    一.前言: 浏览器安全是基于同源策略的.所谓同源策略就是三相同: 1.协议相同: 2.域名相同: 3.端口相同. 但,凡事都是有利弊,同源策略也导致了我们想用AJAX跨域请求,但NO!!为了规避这种限制,其中有一方法就是JSONP. JSONP的基本思想:就是通过<script>的src,向服务器请求数据,且这不受同源策略限制(img和iframe的src也是如此):然后服务器将相应的数据放入指定的函数回调名中,返回给前端. 这,就实现了跨域请求信息. 如下图所示: 了解了JSONP的大体思路

  • nodejs读写json文件的简单方法(必看)

    nodejs 读json文件 var fs=reauire('fs'); var file="d:\\0.json"; var result=JSON.parse(fs.readFileSync( file)); //操作对象 nodejs 写json文件 var coors = {}; coors.left_top = {}; coors.right_top = {}; coors.left_bottom = {}; coors.right_bottom = {}; //填充coor

  • NodeJs读取JSON文件格式化时的注意事项

    进行NodeJs开发时偶然发现的一个雷点 正常情况下从JSON文件读取到字符后再通过JSON.parse没什么问题,只要格式不出错 有时在确保JSON格式正确时仍然会出现unexpected token异常 经过调查发现里面有不会显示的unicode字符 于是确定是UTF-8的问题,utf-8分有dom版和无dom版,一般编辑器不刻意设置会默认保存为带dom的utf8 解决办法是先将读到的文件转成二进制,然后检索dom符号删除 代码实现部分 function readText(pathname)

  • 用nodejs实现json和jsonp服务的方法

    一.JSON和JSONP JSONP的全称是JSON with Padding,由于同源策略的限制,XmlHttpRequest只允许请求当前源(协议,域名,端口)的资源.如果要进行跨域请求,我们可以通过使用html的script标记来进行跨域请求,并在相应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象.这种跨域的通讯方式成为JSONP. 由此我们可以看出两者的区别: json: 一种轻量级的数据格式. jsonp:为实现跨域,而采用的一种脚本注入方法. 备

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

    在编程之前,一定要有一个信条:代码是为了减少工作量而生的,重复枯燥的工作是不能容忍的. 需求 这是由上篇文章衍生出的需求,我已经将一个文件夹内所有的文件名转译为英文,但我在页面上还需要将这些图片引入加载.如果一个一个手写到程序里,未免有点劳心劳神.那么何不将这个文件夹按照存放路径变成一个相应的JSON在前端请求并渲染呢? 说干就干. 文件夹的路径如下所示: 一级路径:test 二级路径:A,B,C...共十三个文件夹 三级路径:每个二级路径下有3-8个文件夹不等 四级路径:a.jpg,b.jpg

  • nodejs遍历文件夹下并操作HTML/CSS/JS/PNG/JPG的方法

    需求描述,由于工作的需要,需要将原本用于1280720的网页改为19201080的网页(电视端页面).需求可以拆分为两部分,代码部分的修改以及图片的修改.在代码部分,需要将所有位置以及大小相关的值乘以1.5,图片的尺寸也要放大1.5倍. 首先使用nodejs遍历当前的文件夹: // 遍历所有的文件 var fs = require("fs") var path = require("path") var relativePath = '\\test' // 拿到需要

  • python 实现将文件或文件夹用相对路径打包为 tar.gz 文件的方法

    默认情况下,tarfile 打包成的 tar.gz 文件会带绝对路径,而很多情况下,我们需要的是相对打包文件夹的路径. 代码: <pre name="code" class="python"><span style="font-size:18px;">import tarfile tmp_tar_dir = "/home" file_name = "test.tar.gz" tmp_

  • python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)

    在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠) 引言 由于win10电脑自带的获取文件路径为双引号括起来的单反斜杠,如下图. "D:\sankey.html" 但是在很多程序里读取文件的时候,文件路径中的反斜杠是会作为反编译的特殊符号,所以无法直接读取该路径 例如在R语言中,读取数据只能用斜杠"/",或者是双反斜杠"\\". 每次在R里读表都很麻烦,要不只能手输,要不用系统自带的路径,然后一个一个加反斜杠. 像我这么懒的人,对于

  • PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法

    本文实例讲述了PHP基于迭代实现文件夹复制.删除.查看大小等操作的方法.分享给大家供大家参考,具体如下: 前面一篇 PHP递归实现文件夹的复制.删除.查看大小操作 分析了递归操作使用技巧,这里再来分析一下迭代的操作技巧. "既然递归能很好的解决,为什么还要用迭代呢"?主要的原因还是效率问题-- 递归的概念是函数调用自身,把一个复杂的问题分解成与其相似的多个子问题来解决,可以极大的减少代码量,使得程序看起来非常优雅. 由于系统要为每次函数调用分配运行空间,并使用压栈予以记录.在函数调用结

  • python+opencv 读取文件夹下的所有图像并批量保存ROI的方法

    如下所示: import cv2 import os import numpy as np root_path = "I:/Images/2017_08_03/" dir = root_path+"images"+"/" count = 0 for root,dir,files in os.walk(dir): for file in files: srcImg = cv2.imread(root_path+"images"+

  • 批处理bat删除指定天数日期之前的文件夹

    [方案一]BAT + REG + VBS 复制代码 代码如下: @echo off ::演示:删除指定路径下指定天数之前(以文件夹的最后修改日期为准)的文件夹. ::如果演示结果无误,把rd前面的echo去掉,即可实现真正删除. ::本例调用了临时VBS代码进行日期计算 ::本例为兼容不同的日期格式,调用reg命令(XP系统自带)统一设置日期格式, ::处理完毕之后再把日期格式恢复成原来的状态. rem 指定待删除文件夹的存放路径 set SrcDir=C:/Test rem 指定天数 set

  • CodeIgniter实现更改view文件夹路径的方法

    控制view文件夹路径的代码:system/core/loader.php public function add_package_path($path, $view_cascade=TRUE) { $path = rtrim($path, '/').'/'; array_unshift($this->_ci_library_paths, $path); array_unshift($this->_ci_model_paths, $path); array_unshift($this->

  • PowerShell中使用Test-Path命令检查文件或文件夹路径是否存在示例

    检查文件或文件夹路径是否存在,在编程中是经常用到的功能.PowerShell对于这个需求提供了一个非常便捷的cmdlet,那就是Test-Path!呵呵,看个名字,你就明白它有多么专业了.看看关于它的基本介绍先: Test-Path,检查路径是否存在. 语法:Test-Path <路径> 说明:这里的路径可以是:文件.文件夹.HKLM路径.环境变量env:路径 下面来举一些例子,让大家更方便懂: 复制代码 代码如下: Test-Path D:\q.txt Test-Path C:\Script

  • ASP.NET 保留文件夹详解

    1. Bin文件夹 Bin文件夹包含应用程序所需的,用于控件.组件或者需要引用的任何其他代码的可部署程序集.该目录中存在的任何.dll文 件将自动地链接到应用程序.如果在该文件夹中留有不用的或过期的文件,则可能出现"二义性引用(ambiguous reference)"异常的风险.换句话说,如果两个不同的程序集定义相同的类(相同的命名空间和名称),则ASP.NET运行库不能决定应该使用哪一 个程序集,从而抛出一个异常.在开发时,当我们重新命名一个项目或一个程序集的名称时,这是常见的错误

随机推荐