Node.js 读取目录中的所有文件,将它们存储在对象中,然后发送对象
我不知道这是否可能,但事情是这样的。而使用回调会让它变得更加困难 我有一个包含html文件的目录,我想用node.js和socket.io将这些文件以对象块的形式发送回客户端 我的所有文件都在/tmpl中 所以套接字需要读取/tmpl中的所有文件 对于每个文件,它必须将数据存储在一个对象中,文件名作为键,内容作为值Node.js 读取目录中的所有文件,将它们存储在对象中,然后发送对象,node.js,Node.js,我不知道这是否可能,但事情是这样的。而使用回调会让它变得更加困难 我有一个包含html文件的目录,我想用node.js和socket.io将这些文件以对象块的形式发送回客户端 我的所有文件都在/tmpl中 所以套接字需要读取/tmpl中的所有文件 对于每个文件,它必须将数据存储在一个对象中,文件名作为键,内容作为值 var data; // this is wrong because it has to loop trough all files. fs.readFile(__dir
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});
最后的回调也是错误的。当目录中的所有文件都完成时,必须调用它
但是我不知道如何创建代码,有人知道这是否可行吗?因此,有三个部分。读取、存储和发送 以下是阅读部分:
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);
});
});
});
}
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(path.resolve(dirname, filename), 'utf-8', function(err, content) {
if (err) {
onError(err);
return;
}
onFileContent(filename, content);
});
});
});
}
以下是存储部分:
var data = {};
readFiles('dirname/', function(filename, content) {
data[filename] = content;
}, function(err) {
throw err;
});
var data = {};
readFiles(path.resolve(__dirname, 'dirname/'), function(filename, content) {
data[filename] = content;
}, function(error) {
throw err;
});
发送部分由您决定。您可能希望一个接一个地发送,或者在阅读完成后发送
如果要在读取完成后发送文件,则应使用同步版本的fs
函数或使用承诺。异步回调不是一种好的样式
此外,您还询问了剥离扩展的问题。你应该一个接一个地提问。没有人会为你写一个完整的解决方案 要使代码在不同的环境中平稳运行,path.resolve可用于操作path的位置。下面是工作得更好的代码 阅读部分:
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);
});
});
});
}
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(path.resolve(dirname, filename), 'utf-8', function(err, content) {
if (err) {
onError(err);
return;
}
onFileContent(filename, content);
});
});
});
}
存储部件:
var data = {};
readFiles('dirname/', function(filename, content) {
data[filename] = content;
}, function(err) {
throw err;
});
var data = {};
readFiles(path.resolve(__dirname, 'dirname/'), function(filename, content) {
data[filename] = content;
}, function(error) {
throw err;
});
这是前一个版本的现代版
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);
});
});
});
}
如何使用它:
简单到:
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 );
});
假设您有另一个文件夹列表,您也可以遍历该列表,因为内部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 );
});
});
它的工作原理
promiseAll
起到了神奇的作用。它接受签名函数(项、索引、解析、拒绝)
的功能块,其中项
是数组中的当前项,索引
它在数组中的位置,解析
和拒绝
回调函数。
每个承诺将在当前索引
处的数组中推送,并通过匿名函数调用将当前项
作为参数:
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);
另一个版本使用Promise的现代方法。其他人基于承诺做出的回应更短:
const readFiles = (dirname) => {
const readDirPr = new Promise( (resolve, reject) => {
fs.readdir(dirname,
(err, filenames) => (err) ? reject(err) : resolve(filenames))
});
return readDirPr.then( filenames => Promise.all(filenames.map((filename) => {
return new Promise ( (resolve, reject) => {
fs.readFile(dirname + filename, 'utf-8',
(err, content) => (err) ? reject(err) : resolve(content));
})
})).catch( error => Promise.reject(error)))
};
readFiles(sourceFolder)
.then( allContents => {
// handle success treatment
}, error => console.log(error));
你是像我一样懒惰的人吗?喜欢npm模块。那么看看这个 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
});
如果您有Node.js 8或更高版本,则可以使用新的util.promisify。(我将代码中与重新格式化为对象有关的部分标记为可选,这是原始帖子要求的。)
对于以下所有示例,您需要导入和安装模块:
const fs=require('fs');
const path=require('path');
异步读取文件
函数读取文件(dir,processFile){
//读取目录
fs.readdir(dir,(错误,文件名)=>{
如果(错误)抛出错误;
fileNames.forEach(文件名=>{
//获取当前文件名
const name=path.parse(filename).name;
//获取当前文件扩展名
const ext=path.parse(filename).ext;
//获取当前文件路径
const filepath=path.resolve(dir,filename);
//获取有关该文件的信息
fs.stat(文件路径,函数(错误,stat){
如果(错误)抛出错误;
//检查当前路径是文件还是文件夹
const isFile=stat.isFile();
//排除文件夹
if(isFile){
//回调,对文件做些什么
processFile(文件路径、名称、ext、stat);
}
});
});
});
}
用法:
//使用文件所在文件夹的绝对路径
readFiles('absolute/path/to/directory/',(filepath、name、ext、stat)=>{
log('file path:',filepath);
log('文件名:',名称);
log('文件扩展名:',ext);
log('文件信息:',stat);
});
同步读取文件、存储在阵列中、自然排序
/**
*@description通过自然排序从文件夹同步读取文件
*@param{String}dir目录的绝对路径
*@返回{Object[]}对象列表,每个对象代表一个文件
*结构如下:`{filepath,name,ext,stat}`
*/
函数readFilesSync(dir){
常量文件=[];
fs.readdirSync(dir.forEach)(文件名=>{
const name=path.parse(filename).name;
const ext=path.parse(filename).ext;
const filepath=path.resolve(dir,filename);
const stat=fs.statSync(文件路径);
const isFile=stat.isFile();
if(isFile)files.push({filepath,name,ext,stat});
});
文件排序((a,b)=>{
//自然排序字母数字字符串
// https://stackoverflow.com/a/38641281
返回a.name.localeCompare(b.name,未定义,{numeric:true,敏感度:'base'});
});
归还文件;
}
用法:
//返回对象的数组列表
//每个对象代表一个文件
const files=readFilesSync('absolute/path/to/directory/');
使用promise异步读取文件
更多信息请点击这里
const{promisify}=require('util');
const readdir_promise=promisify(fs.readdir);
const stat_promise=promisify(fs.stat);
函数readfileasync(dir){
返回readdir_promise(dir,{encoding:'utf8'})
。然后(文件名=>{
const files=getFiles(dir,文件名);
返回承诺。所有(文件);
})
.catch(err=>console.error(err));
}
函数getFiles(dir,filename){
返回filenames.map(文件名=>{
const name=path.parse(filename).name;
const ext=path.parse(filename).ext;
const filepath=path.resolve(dir,filename);
返回stat({name,ext,filepath});