从NodeJS目录中的所有文件中获取CSV

时间:2018-03-21 14:34:44

标签: node.js promise

我尝试从目录中的所有图像中获取CSV文件。我在文件夹中有大约20-30张图片。问题是我的代码只适用于目录中的两个图像,而我使用foreach循环。我无法理解为什么会这样。它就是:

var fs = require('fs');
var jpeg = require('jpeg-js');
var Jimp = require("jimp");
var Promises = require('promise');

fs.readdirSync(`./Photo`).forEach(file => {
  getCsv(`${(__dirname)}/Photo/${file}`);
})

function getCsv(OurFile){
  var promise = new Promises(function (resolve, reject) {
    var error;
    Jimp.read(OurFile, function (err, lenna) {
      if (err) {
        error = err;
        reject(error);
      }
      lenna.write(OurFile);
    })
    if (!error) {
        resolve(OurFile);
    } else {
        reject("Error!");
    }
  });

  promise.then(function (data) {
    return new Promises(function (resolve, reject) {
      var image = new Jimp(data, function (err, image) {
      var w = image.bitmap.width;
      var h = image.bitmap.height;
      resolve(JSON.stringify({
          name : data,
          width : w,
          height : h
        }))
      })
    })
  }).then(function (data) {
    return new Promises(function (resolve, reject) {
      var objectValue = JSON.parse(data);
      var width = objectValue['width'];
      var name = objectValue['name'];
      var jpegData = fs.readFileSync(name);
      var rawImageData = jpeg.decode(jpegData, true); // return as Uint8Array
      var typedarray = rawImageData.data;
      //console.log(typedarray)
      var length = typedarray.length;

      var n = [];
      var i = 0;
      for (l = length + 1; (i + width) < l; i += width) {
          n.push(typedarray.slice(i, i + width));
      }
      resolve(n);
    })
  }).then(function (data) {
      return new Promises(function (resolve, reject) {
        var d = exportToCsv(data);
        fs.writeFile(`${OurFile.split(".")[0]}.csv`, d, function (err) {
          if (err) throw err;
          console.log('Saved!');
        });
      });
    })
  }

function exportToCsv(rows) {
  var processRow = function (row) {
      var finalVal = '';
      for (var j = 0; j < row.length; j++) {
          var innerValue = row[j] === null ? '' : row[j].toString();
          if (row[j] instanceof Date) {
              innerValue = row[j].toLocaleString();
          };
          var result = innerValue.replace(/"/g, '""');
          if (result.search(/("|;|\n)/g) >= 0)
              result = '"' + result + '"';
          if (j > 0)
              finalVal += ';';
          finalVal += result;
      }
      return finalVal + '\n';
  };

  var csvFile = '';
  for (var i = 0; i < rows.length; i++) {
      csvFile += processRow(rows[i]);
  }
  return csvFile;
}

我使用Promises,因为它是处理这些东西逐行运行的唯一方法。

所以,首先我将图像重写为jpeg格式,然后我将其宽度用于将来的解析,然后我以Uint8ClampedArray格式获取我的ImageData,最后将其写入csv文件。

1 个答案:

答案 0 :(得分:0)

试试这个,

var fs = require('fs');
var jpeg = require('jpeg-js');
var Jimp = require("jimp");

function scanDir(folder, files = []) {

    var me = this,
        stats,
        fileContents = fs.readdirSync(folder);

    fileContents.forEach(function(filename) {
        var absFilename = folder + '/' + filename;
        stats = fs.lstatSync(absFilename);
        if(stats.isDirectory(absFilename)) {
            me.scanDir(absFilename, files);
        } else {
            files.push(absFilename);
        }
    });

    return files;
}

function getImageInfos(filename) {
    return new Promise((resolve, reject) => {
        Jimp.read(filename, (err, image) => {
            if(err) {
                reject(err);
            } else {
                resolve({
                    name: filename,
                    width: image.bitmap.width,
                    height: image.bitmap.height
                });
            }
        });
    });
}

function getUInt8Array(file) {

    let typed,
        filename = file.name,
        width = file.width;

    file.uint = [];

    return new Promise((resolve, reject) => {
        fs.readFile(filename, (err, data) => {
            if(err) {
                reject(err);
            } else {

                typed = jpeg.decode(data, true).data;

                for(let c = 0; c < typed.length; c += width) {
                    file.uint.push(typed.slice(c, c + width).join(' '));
                }

                file.uint = file.uint.join('\n');
                resolve(file);
            }
        });
    });
}

function saveIntoCsvFile(file) {

    let filename = file.name.split('.').slice(0, -1).join('.') + '.csv',
        content = [
            '"filename","width","height","content"',
            '"' + Object.keys(file).map((k) => file[k]).join('","') + '"'
        ].join('\n');

    return new Promise((resolve, reject) => {
        fs.writeFile(filename, content, (err) => {
            if(err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
}

let validExtensions = [
    'jpg',
    'jpeg'
];

// scan images and filter files if not images
let files = scanDir('./Photo').filter((file) => {
    let extension = file.split('.').pop();
    return (validExtensions.indexOf(extension) >= 0);
});

let promises = [];

// for each filename get size info and 
// get uint8arr data and finally
// save content in csv file
for(let file of files) {
    promises.push(
        getImageInfos(file)
        .then(getUInt8Array)
        .then(saveIntoCsvFile)
    );
}

// resolve all promises
Promise.all(promises)
.then(() => {
    console.log('end');
})
.catch((err) => {
    console.error(err);
});