使用Node.js在控制台中,展示文件目录

期待效果:想要用node做一个小Demo,显示 一级文件夹 下的文件列表,在选中 二级文件 的时候显示文件信息,在选中 二级文件夹 的时候,显示该文件夹下的文件列表。

问题:在选中三级文件的时候出问题了,stdin.on('data', xxx)多执行了。

目录结构:
图片描述

代码:


var fs = require('fs'),
    stdin = process.stdin,
    stdout = process.stdout,
    aFiles = [],
    noData = true;

readdir(__dirname);

function readdir (path) {
    fs.readdir(path, function (err, files) {
        if (err) {
            console.log('error:1');
            return console.error(err);
        }

        aFiles = JSON.parse(JSON.stringify(files));

        file(0, path, aFiles);
    })
}

// 显示文件列表
function file(i, path, aFiles) {
    var filename = aFiles[i];

    // 使用异步获取文件信息
    fs.stat(path + '/' + filename, function (err, stat) {
        if (err) {
            console.log('error:2');
            return console.error(err);
        }

        // 判断是否为文件夹
        if (stat.isDirectory()) {
            console.log('    ' + i + '    \033[36m' + filename + '/\033[39m');
        } else {
            console.log('    ' + i + '    \033[90m' + filename + '\033[39m');
        }

        i++;
        if (aFiles.length != i) {
            file(i, path, aFiles);
        } else {
            read(path, aFiles);
        }
    })
}

// i/0流
function read (path, aFiles) {
    console.log('');
    stdout.write('    \033[33mEnter your choice:\033[39m');
    stdin.resume();

    stdin.on('data', function (data) {
        var idx = parseInt(data.toString());
        var filename = aFiles[idx];

        if (!filename) {
            stdout.write('    \033[33mEnter your choice:\033[39m');
            
        } else {
            stdin.pause();
            readfile(filename, path);
        }
    })    
}

// 读取文件
function readfile (filename, path, aFiles) {
    var nextPath = path + '/' + filename;
    fs.stat(nextPath, function (err, stat) {
        if (err) {
            return console.error(err);
        }

        if (stat.isDirectory()) {
            readdir(nextPath);

        } else {
            fs.readFile(nextPath, function (err, data) {
                if (err) {
                    return console.error(err);
                }
                console.log('');    // 同console.log('\n');
                console.log('    \033[90m' + data.toString().replace(/(.*)/g, '    $1') + '\033[39m');
            })
        }
    })
}

    

错误图片:
图片描述

阅读 2.5k
2 个回答

首先你代码中存在一个问题,data事件会重复绑定,在读文件之前需要移除之前的绑定。
至于你问的问题,为何没结束,是因为data事件还在监听,退出进程或者销毁关闭这个流即可。如下所示。

var fs = require('fs'),
    stdin = process.stdin,
    stdout = process.stdout,
    aFiles = [],
    noData = true;

readdir(__dirname);

function readdir (path) {
    fs.readdir(path, function (err, files) {
        if (err) {
            console.log('error:1');
            return console.error(err);
        }

        aFiles = JSON.parse(JSON.stringify(files));

        file(0, path, aFiles);
    })
}

// 显示文件列表
function file(i, path, aFiles) {
    var filename = aFiles[i];

    // 使用异步获取文件信息
    fs.stat(path + '/' + filename, function (err, stat) {
        if (err) {
            console.log('error:2');
            return console.error(err);
        }

        // 判断是否为文件夹
        if (stat.isDirectory()) {
            console.log('    ' + i + '    \033[36m' + filename + '/\033[39m');
        } else {
            console.log('    ' + i + '    \033[90m' + filename + '\033[39m');
        }

        i++;
        if (aFiles.length != i) {
            file(i, path, aFiles);
        } else {
            read(path, aFiles);
        }
    })
}

// i/0流
function read (path, aFiles) {
    console.log('');
    stdout.write('    \033[33mEnter your choice:\033[39m');
    stdin.resume();

    stdin.on('data', function (data) {
        var idx = parseInt(data.toString());
        var filename = aFiles[idx];

        if (!filename) {
            stdout.write('    \033[33mEnter your choice:\033[39m');

        } else {
            stdin.pause();
            readfile(filename, path, stdin);
        }
    })
}
stdin.on('close',() => console.log('close'))
// 读取文件
function readfile (filename, path, stdin) {
    var nextPath = path + '/' + filename;
    fs.stat(nextPath, function (err, stat) {
        if (err) {
            return console.error(err);
        }

        if (stat.isDirectory()) {
            readdir(nextPath);
            stdin.removeAllListeners()

        } else {
            fs.readFile(nextPath, function (err, data) {
                if (err) {
                    return console.error(err);
                }
                console.log('');    // 同console.log('\n');
                console.log('    \033[90m' + data.toString().replace(/(.*)/g, '    $1') + '\033[39m');
                stdin.destroy()

            })
        }
    })
}

找到解决方法了,不用on绑定data,用once绑定就好了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题