Javascript 如何使用node.js按顺序列出目录的内容?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6246238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 20:55:07  来源:igfitidea点击:

How to list contents of a directory IN ORDER with node.js?

javascriptlistnode.jsdirectoryinorder

提问by Brandon

I'm a fairly experienced programmer and I've just recently discovered node.js. I love JavaScript because that's where I started (Web Development) so being able to write server-side code with its is amazing.

我是一个相当有经验的程序员,我最近才发现 node.js。我喜欢 JavaScript,因为那是我开始(Web 开发)的地方,因此能够用它编写服务器端代码真是太棒了。

Currently, I'm working on a simple exercise, a WebSocket/HTTP server, and I began to add a directory list function when I ran into a slight annoyance: when I list directories and files in a certain directory they're not in any order. I would like them to be listed with directories first, files second than alphabetically (like the 'ls' command). I have a feeling its because its asynchronus but I'm not totally positive. Any help would be appreciated.

目前,我正在做一个简单的练习,一个WebSocket/HTTP服务器,当我遇到一个小烦恼时,我开始添加目录列表功能:当我列出某个目录中的目录和文件时,它们不在任何目录中命令。我希望它们首先与目录一起列出,然后按字母顺序排列文件(如“ls”命令)。我有一种感觉,因为它是异步的,但我并不完全肯定。任何帮助,将不胜感激。

BTW, here's my code:

顺便说一句,这是我的代码:

var sys = require("sys");
var ws = require('websocket-server');
var fs = require("fs");
var path = require("path");
var url = require("url");

function log(data){
  sys.log("3[0;32m"+data+"3[0m");
}

var server = ws.createServer();
server.listen(3400);
log("Listening on 3400 for HTTP and WS");

server.addListener("request", function(request, response){
  log("HTTP: Connected: " + request.connection.remoteAddress);
  var uri = url.parse(request.url).pathname;
  var filename = path.join("/home/brandon", uri);
  log("HTTP: " + request.connection.remoteAddress + " Requested: " + filename);
  path.exists(filename, function(exists) {
        if(!exists) {
            response.writeHead(404, {"Content-Type": "text/plain"});
            response.write("404 Not Found\n");
            log("HTTP: " + filename + " Does Not Exist. 404 returned to " + request.connection.remoteAddress);
            response.end();
            log("HTTP: Disconnected: " + request.connection.remoteAddress);
            return;
        }

        fs.readFile(filename, "binary", function(err, file) {
            if(err) {
                if(err.errno === 21){
                    fs.readdir(filename, function(err1, files){
                        if(err1){ 
                            response.writeHead(500, {"Content-Type": "text/plain"});
                            response.write("Error when reading directory: " + err1 + "\n");
                            log("HTTP: " + filename + " Could Not Be Read. 500 returned to " + request.connection.remoteAddress);
                            response.end();
                            log("HTTP: Disconnected: " + request.connection.remoteAddress);
                            return;
                        } else {
                            response.writeHead(200);
                            response.write("<HTML><HEAD><title>Directory Listing for " + uri + "</title></HEAD><BODY><h1>Directory Listing for " + uri + "</h1>");
                            response.write("<ul>");
                            function printBr(element, index, array) {
                                response.write("<li>" + element + "</li>");
                            }
                            /*for( i in files ){
                                response.write("<li>" + files[i] + "</li>");
                            }*/
                            files.forEach(printBr);
                            response.write("</ul>");
                            response.write("</BODY></HTML>");
                            log("HTTP: Directory listing for " + filename + " sent to " + request.connection.remoteAddress);
                            response.end();
                            log("HTTP: Disconnected: " + request.connection.remoteAddress);
                            return;
                        }
                    });
                    return;
                }
                response.writeHead(500, {"Content-Type": "text/plain"});
                response.write("Error when reading file: " + err + "\n");
                log("HTTP: " + filename + " Could Not Be Read. 500 returned to " + request.connection.remoteAddress);
                response.end();
                log("HTTP: Disconnected: " + request.connection.remoteAddress);
                return;
            }

            response.writeHead(200);
            response.write(file, "binary");
            log("HTTP: " + filename + " Read and Sent to " + request.connection.remoteAddress);
            response.end();
            log("HTTP: Disconnected: " + request.connection.remoteAddress);
        });
    });
});

server.addListener("connection", function(conn){
  log(conn.id + ": new connection");
  server.broadcast("New Connection: "+conn.id);
  conn.addListener("readyStateChange", function(readyState){
    log("stateChanged: "+readyState);
  });

  conn.addListener("close", function(){
    var c = this;
    log(c.id + ": Connection Closed");
    server.broadcast("Connection Closed: "+c.id);
  });

  conn.addListener("message", function(message){
    log(conn.id + ": "+JSON.stringify(message));

    server.broadcast(conn.id + ": "+message);
  });
});

And here's the output in the browser: Output in Browser

这是浏览器中的输出: 浏览器输出

**SOLVED:**

**解决了:**

Thanks to @Samir, I found out how to do exactly what I wanted to do. I iterated through the array of the directory contents, checked if an item was a directory or file, separated them into two arrays ('dirs_in' for dirs and 'files_in' for files), sorted the two arrays alphabetically, and finally wrote them out.

感谢@Samir,我找到了如何做我想做的事情。我遍历目录内容的数组,检查一个项目是目录还是文件,将它们分成两个数组('dirs_in' 表示目录,'files_in' 表示文件),按字母顺序对这两个数组进行排序,最后将它们写出来.

Code (Lines 42-70):

代码(第 42-70 行):

response.writeHead(200);
response.write("<HTML><HEAD><title>Directory Listing for " + uri + "</title></HEAD><BODY><h1>Directory Listing for " + uri + "</h1>");
response.write("<ul>");
function printBr(element, index, array) {
    response.write("<li>" + element);
    if( fs.statSync( path.join(filename + element) ).isDirectory() ){
        response.write(" is a <b>dir</b>");
    } else {
        response.write(" is a <b>file</b>");
    }
    response.write("</li>");
}
var dirs_in = [];
var files_in = [];
function sep(element, index, array) {
    if( fs.statSync( path.join(filename + element) ).isDirectory() ){
        dirs_in.push(element);
    } else {
        files_in.push(element);
    }
}
files.forEach(sep);
dirs_in.sort().forEach(printBr);
files_in.sort().forEach(printBr);
response.write("</ul>");
response.write("</BODY></HTML>");
log("HTTP: Directory listing for " + filename + " sent to " + request.connection.remoteAddress);
response.end();
log("HTTP: Disconnected: " + request.connection.remoteAddress);

Browser Output: Problem SolvedP.S. I'll remove the 'is a dir' and 'is a file'. They were just for testing.

浏览器输出: 问题解决了PS 我将删除“是一个目录”和“是一个文件”。他们只是为了测试。

回答by Samir Talwar

If you want them ordered by name, you can just call sort()on the array first.

如果您希望它们按名称排序,您可以sort()先调用数组。

files.sort().forEach(printBr);

If, for example, you'd like to sort directories first, then you need to get more information. A naive implementation would be to query the stats of each file in the sort comparison function:

例如,如果您想先对目录进行排序,那么您需要获取更多信息。一个简单的实现是在排序比较函数中查询每个文件的统计信息:

files.sort(function(a, b) {
    var aIsDir = fs.statSync(dir + "/" + a).isDirectory(),
        bIsDir = fs.statSync(dir + "/" + b).isDirectory();

    if (aIsDir && !bIsDir) {
        return -1;
    }

    if (!aIsDir && bIsDir) {
        return 1;
    }

    return a.localCompare(b);
}).forEach(printBr);

The localComparemethod is what the sortmethod uses by default as the comparison function, so we delegate to that if they're both on "equal" terms. You can expand upon this as necessary. I'd also recommend you store the result of isDirectoryin a map or something at the very least. In addition, statSyncis good for demonstration purposes, but not in production code. Use statinstead. This does lead to slightly more complex code, but the benefits of asynchronous behaviour are worth it.

localCompare方法是该sort方法默认使用的比较函数,因此如果它们都处于“相等”条件,则我们将其委托给该方法。您可以根据需要对此进行扩展。我还建议您isDirectory至少将结果存储在地图或其他东西中。此外,statSync有利于演示目的,但不适用于生产代码。使用stat来代替。这确实会导致代码稍微复杂一些,但异步行为的好处是值得的。