本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2019-11-21
需求:
1、程序需要在命令行运行,通过终端与用户交互
2、程序启动后,需要显示当前目录列表
3、选择某个文件后,程序需要显示该文件的内容。
4、选择一个目录时,程序显示该目录下的信息。
5、运行结束后程序退出。
// index.js
var fs = require('fs');
var stdin = process.stdin;
var stdout = process.stdout;
var stats = []; // 存储读取文件或者目录的元数据
// readdir 异步 - 读取目录
// 读取当前目录 __dirname 表示当前执行文件时该文件在文件系统中所在的目录
fs.readdir(__dirname, function(err, files) {
// files 是一个数组 包含当前目录下的 文件和目录 的名称
if(!files.length) {
return console.log('\033[31m No files to show!\033[39m\n'); // 输出文字呈红色
}
console.log(' Select which file or directory want to see\n');
function file(i) {
var filename = files[i];
// stat会给出文件或者目录的元数据
fs.stat(__dirname + '/' + filename, (err, stat) => {
stats[i] = stat;
// 根据是目录还是文件 展示不同的颜色
if(stat.isDirectory()) {
console.log(' ' + i +' \033[36m' + filename + '\033[39m'); // 蓝色
} else {
console.log(' ' + i +' \033[90m' + filename + '\033[39m'); // 灰色
}
i++;
if (i == files.length) { // 读取完成 与用户交互
read();
} else {
file(i); // 递归
}
})
}
file(0); // 调用一次 file函数会内部递归 读取所有文件
// 读取用户输入
function read() {
console.log('');
stdout.write(' \033[33mEnter your choice: \033[39m'); // 黄色
// 标准输入流默认是暂停 (pause) 的,所以必须要调用 process.stdin.resume() 来恢复 (resume) 接收:
stdin.resume();
stdin.setEncoding('utf-8'); //设置编码
stdin.on('data', data => { // 监听用户输入
var filename = files[Number(data)]
if(!filename) {
stdout.write(' \033[31mEnter your choice: \033[39m'); // 红色5 不存在则重新选择
} else {
// 如果检查通过,我们要确保再次将流暂停(回到默认状态),以便于之后做完fs操作后,程序顺利退出。
stdin.pause();
// 展示
if(stats[Number(data)].isDirectory()) { // 如果是目录展示目录下的文件
fs.readdir(__dirname + '/' + filename, (err, files) => {
console.log('');
console.log(`(${files.length} files)`); // 目录下的总文件数
files.forEach(file => { //file 是目录下的文件或目录名称
console.log(' - '+ file);
})
})
} else { // 如果是文件直接展示文件内容
fs.readFile(__dirname + '/' + filename, 'utf-8', (err, data) => {
console.log('');
console.log('\033[90m' + data + '\033[39m');
})
}
}
})
}
})
// process的输入输出
// stdout 标准输出 可写流
// stdin 标准输入 可读流 状态默认是暂停的
// stderr 标准错误 可写流
process.argv
包含了所有Node程序运行时的参数。返回一个数组,第一个元素始终是node所在的目录,第二个元素始终是执行的文件路径,紧接着是命令行后跟着的参数。
// index.js
console.log(process.argv);
// node index.js --name=jack --hello
// [ '/usr/local/bin/node',
// '/Users/cz/Desktop/Test/index1.js',
// '--name=jack',
// '--hello' ]
// 所以获取有用参数常常这么用
process.argv.slice(2);
// 使用yargs模块可以解析参数 第三方包
var argv = require('yargs').argv;
console.log(argv.name) // jack
// 更可以指定参数名的别名 简化命令
var argv = require('yargs').alias('n', 'name').argv;
// 这样 node index.js --name jack 与 node index.js -n jack一致
console.log(argv.n) // jack
// 当前js所在的路径:/Users/cz/Desktop/Test/test.js
console.log(__dirname);
console.log(process.cwd());
// /Users/cz/Desktop/Test
// /Users/cz/Desktop
__dirname
: 获取执行文件时该文件在文件系统中所在的目录
process.cwd()
: 获取当前工作目录, 比如我们在桌面的终端目录下node ./Test/test.js
,此时的桌面目录就是工作目录,返回/Users/cz/Desktop
。
process.chdir(path)
: 更改工作目录。
NODE_ENV="prd" node
> process.env.NODE_ENV
'prd'
> process.env.SHELL
'/bin/bash'
要让一个程序退出,可以调用process.exit()
并提供一个退出代码,比如,当错误发生时,要退出程序,通常使用代码1。
console.error('An Error occurred')
process.exit(1);
进程和操作系统进行通信的其中一种方式就是信号,比如,要进程终止,可以发送SIGKILL信号。
发送信号的方法如下。
$ kill -s SIGKILL [process_id]
process对象能够监听信号事件
process.on('SIGKILL', function() {
console.log('Got a sign')
process.exit(0);
})
console.log('\033[90m' + data + '\033[39m');
\033表示转义序列开始
[表示开始颜色设置
90设置当前颜色
m表示设置颜色结束
最后结尾的是将颜色设置还原,下一次输出依然是设置前的默认颜色39。
有些文件太大的话,使用fs.readFile读取不太合适,需要使用流操作,createReadStream是给你一个ReadableStream,你可以监听它的’data’,一点一点儿处理文件,用过的部分会被GC(垃圾回收),所以占内存少。 readFile是把整个文件全部读到内存里。
var stream = fs.createReadStream('files.txt');
var str = '';
stream.on('data', function(chunk){
str += chunk
});
stream.on('end', function(chunk){
console.log(str);
});
流式读取,管道操作。
require('http').createServer(function(req, res) {
res.write(200,{'Content-Type':'image/png'});
require('fs').createReadStream('image.png').pipe(res);
// 等同于
var stream = require('fs').createReadStream('image.png');
stream.on('data', function(data){
res.write(data);
});
stream.on('end', function(chunk){
res.end();
});
})
有人喜欢用一种可以编译为CSS的语言来书写CSS样式,这个时候,就可以使用监视功能,当源文件发生改变时,就将其编译为CSS文件。
var fs = require('fs');
var files = fs.readdirSync(procwss.cwd()); // 同步读取当前工作目录文件
files.forEach(file => {
// 监听.less后缀的文件
if(/\.less/.test(file)) {
fs.watchFile(process.cwd() + '/' + file, function() {
console.log(file + 'changed!');
// 执行编译
// do something
})
}
})