1. 查询和读写文件
(1) 处理文件路径(var path = require('path');)
A: path.normalize() 规范化路径
B:path.join() 连接路径
C:path.resolve() 解析路径
…………
(2) 文件读取写入(var fs = require('fs');)
var fs =require('fs');
fs.open('./file.text','r', function opened(err, fd){
if (err){
throw err;
}
var readbuffer = new Buffer(1024),
bufferOffset = 0,
bufferLength = readbuffer.length,
filePosition = 0;
fs.read(fd, readbuffer, bufferOffset,bufferLength, filePosition, function read(err, readbytes){
if(err){
throw err;
}
console.log("read"+readbytes+"bytes");
if (readbytes >0){
console.log(readbuffer.slice(0,readbytes));
}
});
});
2. 执行外部命令。
当需要执行一个外部shell命令,或者可执行文件时,可以使用child_process模块。
var chile_process = require('child_process');
chile_process.exec("ls",function(err, stdout, stderr){
if (err){
throw err;
}
console.log(stdout);
});
.exec()还包含一个若干配置选项的可选参数,这个参数放在回调函数之前。
3. 生成子进程。
Node的child_process模块,允许对子进程的启动、终止、交互,以及更精细的控制。创建子进程后,就会创建一个双向通信通道,两个进程可以利用这条通道互相收发字符串形式的数据。父进程还可对子进程施加一些控制,甚至终止子进程。
(1) 创建进程(通过创建子进程来执行外部命令)
varchild_process = require('child_process');
var child = child_process.spawn('', ''); //创建进程 有些参数??
(2) 监听子进程输出数据
child.stdout.on('data',function(data){});
(3) 子进程可以使用process.stdin流来监听数据。但是首先要恢复流。
process.stdin.resume(); //解除stdin流的暂停状态
process.stdin.on("data",function(data){ //监听输入数据
var number;
try{
number = parseInt(data.toString(), 10);
number += 1;
process.stdout.write(number +"\n"); //输出加1后的数
}catch (err){
process.stderr.write(err.message +"\n");
}
});
说明:单执行这个代码,运行之后,应用程序等待输入,如果输入一个数字按回车,就会在屏幕上得到一个加1后返回的数据。
(4) 父子进程交互
var child_process = require('child_process');
//创建一个node子进程 执行test.js程序 就是(3)中的代码
//在cmd下 node test.js 可以执行这个test.js
var child= child_process.spawn('node', ['test.js']);
setInterval(function(){
var number = Math.floor(Math.random()*10);
//将该随机数发送到子进程
child.stdin.write(number + "\n");
//获得子进程响应并打印出来
child.stdout.once('data', function(data){
//这里能访问到number就是闭包
console.log('chile replied to'+number+'with:'+data);
});
},1000);
child.stderr.on('data',function(data){
process.stdout.write(data);
});
说明:创建子进程后,就会启动了一个运行(3)中代码的子进程。然后将产生的随机数作为一个字符串发送给子进程,等待子进程返回一个字符串。
(5) 当子进程退出时,获得通知
child.on('exit', function(code, signal){});
监听子进程的‘exit‘事件,当该事件出现时执行回调函数,回调函数有两个参数。第一个是:退出码,第二个是:退出信号。
4. 读写数据流
流是由几个node对象实现的抽象概念,创建和获取流的方式取决于使用流的类型。例如文件和TCP套接字。
代表数据的向内流动(可读流)和代表数据的向外流动(可写流)
(1) 使用可读流
在创键和获取一个可读流后(创建或者获取可读流的方法取决于流的类型)可以对其进行控制。可以通过暂停或者恢复来控制数据流动,可以在数据可用时得到通知,并且流终止时,你也会得到通知并能关闭它。
A: 等待数据
流能够以块为单位发送数据,通过监听data事件,就会得到数据后获得通知。
B: 暂停与恢复流
stream.pause(); 暂停流
stream.resume(); 恢复流
C:了解流终止 监听end 事
Stream.on(‘end’,function(){});
(2) 用文件路径创建一个可读流
var fs =require('fs');
var stream = fs.createReadStream('path/to/file');
fs.createReadStream()可传递第二个可选参数。包括:
- encoding: “data”事件发送的字符串编码方式
- fd: 如果有打开的文件描述符,则可传入该选项
- bufferSize: 要被读取的每个文件块大小 默认64KB
- start: 文件中第一个被读取的字节位置
- end: 文件中最后一个被读取的字节位置
eg:
var fs = require('fs');
var path = "/path/to/my/file";
fs.open(path, 'r', function(err, fd){
fs.createReadStream(null,{encoding : 'utf8', fd : fd});
fs.on('data', function(data){});
});
(3) 创建文件可写流
fs.createWriteStream(path,options);
options默认为:
{ flags : ‘w’ , 打开文件方式
encoding : null,
mode : 0666 指定打开文件权限
}
(4) 避免慢客户端问题(利用终止流)
var http= require('http');
var fs =require('fs');
http.createServer(function(req,res){
var rs =fs.createReadStream('./file.text') // 读大文件
rs.on('data', function(data){
if(!res.write(data)){
rs.pause(); // 核缓冲区被填满就暂停可读流
}
});
res.on('drain', function(){ //流被清空
rs.resume(); //当可写流完成接收数据时,再恢复可读流
});
rs.end('end', function(){ //流终止
res.end();
});
}).listen(8080);
说明:上面例子创建了一个HTTP服务器在8080端口上监听,并将文件file.text的内容提交给所有的HTTP请求。如果write命令无法将可读流数据传入核缓冲区中(什么是核缓冲区?),就暂停可读流,当可写流完成接收数据时,就会恢复可读流。执行上面代码后,在浏览器输入127.0.0.1:8080就可以读取到file.text的内容。
(5) 避免慢客户端问题(应用stream.pipe())
暂停可读流直到可写流赶上并在之后恢复可读流是一种循环模式。可以使用stream.pipe()命令实现这种模式。它是可读流接口的一部分(由传输源调用)并接受目标可写流作为第一个参数。第二个是可选参数。
上面例子重写:
var http= require('http');
var fs =require('fs');
http.createServer(function(req,res){
varrs = fs.createReadStream('./file.text') // 读大文件
rs.pipe(res);
}).listen(8080);