读取目录中的所有文件,将它们存储在对象中,然后发送对象

Sai*_*han 72 node.js

我不知道这是否可行,但这里有.使用回调使得它变得更加困难.

我有一个带有html文件的目录,我想用node.js和socket.io以Object块的形式发送回客户端.

我的所有文件都在/ tmpl中

所以socket需要读取/ tmpl中的所有文件.

对于每个文件,它必须将数据存储在以文件名作为键的对象中,并将内容作为值存储.

  var data;
  // this is wrong because it has to loop trough all files.
  fs.readFile(__dirname + '/tmpl/filename.html', 'utf8', function(err, html){
      if(err) throw err;
      //filename must be without .html at the end
      data['filename'] = html;
  });
  socket.emit('init', {data: data});
Run Code Online (Sandbox Code Playgroud)

最后的回调也是错误的.必须在目录中的所有文件完成时调用它.

但我不知道如何创建代码,任何人都知道这是否可能?

ste*_*ewe 144

所以,有三个部分.阅读,存储和发送.

这是阅读部分:

var fs = require('fs');

function readFiles(dirname, onFileContent, onError) {
  fs.readdir(dirname, function(err, filenames) {
    if (err) {
      onError(err);
      return;
    }
    filenames.forEach(function(filename) {
      fs.readFile(dirname + filename, 'utf-8', function(err, content) {
        if (err) {
          onError(err);
          return;
        }
        onFileContent(filename, content);
      });
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

这是存储部分:

var data = {};
readFiles('dirname/', function(filename, content) {
  data[filename] = content;
}, function(err) {
  throw err;
});
Run Code Online (Sandbox Code Playgroud)

发送部分取决于您.您可能希望逐个发送或在完成阅读后发送它们.

如果要在读取完成后发送文件,则应使用同步版本的fs函数或使用promises.异步回调不是一个好的风格.

另外,您询问有关剥离扩展的问题.你应该逐个处理问题.没有人会为您编写完整的解决方案.

  • 由于异步性质,foreach循环最有可能在返回第一个`readFile` html之前完成,因此`c`应立即上升到`x`(文件数),然后当html从磁盘到达时递减(这是很久以后) (4认同)

lor*_*isi 16

这是Promise前一个版本的现代版本,使用一种Promise.all方法在读取所有文件时解析所有承诺:

/**
 * Promise all
 * @author Loreto Parisi (loretoparisi at gmail dot com)
 */
function promiseAllP(items, block) {
    var promises = [];
    items.forEach(function(item,index) {
        promises.push( function(item,i) {
            return new Promise(function(resolve, reject) {
                return block.apply(this,[item,index,resolve,reject]);
            });
        }(item,index))
    });
    return Promise.all(promises);
} //promiseAll

/**
 * read files
 * @param dirname string
 * @return Promise
 * @author Loreto Parisi (loretoparisi at gmail dot com)
 * @see http://stackoverflow.com/questions/10049557/reading-all-files-in-a-directory-store-them-in-objects-and-send-the-object
 */
function readFiles(dirname) {
    return new Promise((resolve, reject) => {
        fs.readdir(dirname, function(err, filenames) {
            if (err) return reject(err);
            promiseAllP(filenames,
            (filename,index,resolve,reject) =>  {
                fs.readFile(path.resolve(dirname, filename), 'utf-8', function(err, content) {
                    if (err) return reject(err);
                    return resolve({filename: filename, contents: content});
                });
            })
            .then(results => {
                return resolve(results);
            })
            .catch(error => {
                return reject(error);
            });
        });
  });
}
Run Code Online (Sandbox Code Playgroud)

如何使用它:

就像这样简单:

readFiles( EMAIL_ROOT + '/' + folder)
.then(files => {
    console.log( "loaded ", files.length );
    files.forEach( (item, index) => {
        console.log( "item",index, "size ", item.contents.length);
    });
})
.catch( error => {
    console.log( error );
});
Run Code Online (Sandbox Code Playgroud)

假设您有另一个文件夹列表,您可以迭代此列表,因为内部promise.all将以异步方式解析每个文件夹:

var folders=['spam','ham'];
folders.forEach( folder => {
    readFiles( EMAIL_ROOT + '/' + folder)
    .then(files => {
        console.log( "loaded ", files.length );
        files.forEach( (item, index) => {
            console.log( "item",index, "size ", item.contents.length);
        });
    })
    .catch( error => {
        console.log( error );
    });
});
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

promiseAll是神奇的.这需要签名的功能块function(item,index,resolve,reject),其中item为阵列中的当前项,index其在阵列中的位置,以及resolvereject所述Promise回调函数.每个promise将被推送到当前的数组中,indexitem通过匿名函数调用当前作为参数:

promises.push( function(item,i) {
        return new Promise(function(resolve, reject) {
            return block.apply(this,[item,index,resolve,reject]);
        });
    }(item,index))
Run Code Online (Sandbox Code Playgroud)

然后所有的承诺都将得到解决:

return Promise.all(promises);
Run Code Online (Sandbox Code Playgroud)


pld*_*ldg 7

对于下面的所有示例,您需要导入fs路径模块:

const fs = require('fs');
const path = require('path');
Run Code Online (Sandbox Code Playgroud)

异步读取文件

function readFiles(dir, processFile) {
  // read directory
  fs.readdir(dir, (error, fileNames) => {
    if (error) throw error;

    fileNames.forEach(filename => {
      // get current file name
      const name = path.parse(filename).name;
      // get current file extension
      const ext = path.parse(filename).ext;
      // get current file path
      const filepath = path.resolve(dir, filename);

      // get information about the file
      fs.stat(filepath, function(error, stat) {
        if (error) throw error;

        // check if the current path is a file or a folder
        const isFile = stat.isFile();

        // exclude folders
        if (isFile) {
          // callback, do something with the file
          processFile(filepath, name, ext, stat);
        }
      });
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

用法:

// use an absolute path to the folder where files are located
readFiles('absolute/path/to/directory/', (filepath, name, ext, stat) => {
  console.log('file path:', filepath);
  console.log('file name:', name);
  console.log('file extension:', ext);
  console.log('file information:', stat);
});
Run Code Online (Sandbox Code Playgroud)

同步读取文件,存储在数组中,自然排序

/**
 * @description Read files synchronously from a folder, with natural sorting
 * @param {String} dir Absolute path to directory
 * @returns {Object[]} List of object, each object represent a file
 * structured like so: `{ filepath, name, ext, stat }`
 */
function readFilesSync(dir) {
  const files = [];

  fs.readdirSync(dir).forEach(filename => {
    const name = path.parse(filename).name;
    const ext = path.parse(filename).ext;
    const filepath = path.resolve(dir, filename);
    const stat = fs.statSync(filepath);
    const isFile = stat.isFile();

    if (isFile) files.push({ filepath, name, ext, stat });
  });

  files.sort((a, b) => {
    // natural sort alphanumeric strings
    // https://stackoverflow.com/a/38641281
    return a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' });
  });

  return files;
}
Run Code Online (Sandbox Code Playgroud)

用法:

// return an array list of objects
// each object represent a file
const files = readFilesSync('absolute/path/to/directory/');
Run Code Online (Sandbox Code Playgroud)

使用promise读取文件异步

关于更多信息promisify文章.

const { promisify } = require('util');

const readdir_promise = promisify(fs.readdir);
const stat_promise = promisify(fs.stat);

function readFilesAsync(dir) {
  return readdir_promise(dir, { encoding: 'utf8' })
    .then(filenames => {
      const files = getFiles(dir, filenames);

      return Promise.all(files);
    })
    .catch(err => console.error(err));
}

function getFiles(dir, filenames) {
  return filenames.map(filename => {
    const name = path.parse(filename).name;
    const ext = path.parse(filename).ext;
    const filepath = path.resolve(dir, filename);

    return stat({ name, ext, filepath });
  });
}

function stat({ name, ext, filepath }) {
  return stat_promise(filepath)
    .then(stat => {
      const isFile = stat.isFile();

      if (isFile) return { name, ext, filepath, stat };
    })
    .catch(err => console.error(err));
}
Run Code Online (Sandbox Code Playgroud)

用法:

readFiles('absolute/path/to/directory/')
  // return an array list of objects
  // each object is a file
  // with those properties: { name, ext, filepath, stat }
  .then(files => console.log(files))
  .catch(err => console.log(err));
Run Code Online (Sandbox Code Playgroud)

注意:返回undefined文件夹,如果需要,可以将其过滤掉:

readFiles('absolute/path/to/directory/')
  .then(files => files.filter(file => file !== undefined))
  .catch(err => console.log(err));
Run Code Online (Sandbox Code Playgroud)


Bim*_*Grg 5

你是不是像我一样懒惰并且喜欢npm 模块:D 然后看看这个。

npm 安装节点目录

读取文件的示例:

var dir = require('node-dir');

dir.readFiles(__dirname,
    function(err, content, next) {
        if (err) throw err;
        console.log('content:', content);  // get content of files
        next();
    },
    function(err, files){
        if (err) throw err;
        console.log('finished reading files:', files); // get filepath 
   });    
Run Code Online (Sandbox Code Playgroud)


Sac*_*ani 5

我刚刚写了这个,对我来说它看起来更干净:

const fs = require('fs');
const util = require('util');

const readdir = util.promisify(fs.readdir);
const readFile = util.promisify(fs.readFile);

const readFiles = async dirname => {
    try {
        const filenames = await readdir(dirname);
        console.log({ filenames });
        const files_promise = filenames.map(filename => {
            return readFile(dirname + filename, 'utf-8');
        });
        const response = await Promise.all(files_promise);
        //console.log({ response })
        //return response
        return filenames.reduce((accumlater, filename, currentIndex) => {
            const content = response[currentIndex];
            accumlater[filename] = {
                content,
            };
            return accumlater;
        }, {});
    } catch (error) {
        console.error(error);
    }
};

const main = async () => {

    const response = await readFiles(
        './folder-name',
    );
    console.log({ response });
};
Run Code Online (Sandbox Code Playgroud)

response您可以根据需要修改格式。此代码的格式response如下所示:

{
   "filename-01":{
      "content":"This is the sample content of the file"
   },
   "filename-02":{
      "content":"This is the sample content of the file"
   }
}

Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

111998 次

最近记录:

5 年,10 月 前