路径操作
文件描述符句柄在node中是一个整数,其中1,2,3分别表示标准输入文件,标准输出文件,标准错误文件的描述符。
规范化路径:
path.normalize('/foo/bar//baz/asdf/quux/..')///foo/bar/baz/asdf
连接路径:
path.join('/foo','bar','baz/asdf','quux','..')//'/foo/bar/baz/asdf'
;
解析路径:
path.resolve('/foo/bar','./baz');//'/foo/bar/baz'
path.resolve('/foo/bar','/tmp/file/');//'/tmp/file'
如果解析的结果不是绝对路径,那么path.resolve函数会将当前工作目录附加到解析结果的前面。
获取文件路径的目录部分:
path.dirname('/foo/bar/quux.txt');//'/foo/bar'
从文件路径中提取文件名:
path.basename('/foo/bar/quux.html');//'quux.html'
path.basename('/foo/bar/quux.html','.html');//'quux'
path.extname('/foo/bar/quux.html');//'.html'
判断目录是否存在:
//该方法是path唯一与文件系统交互的
path.exists('/etc/passwd',function(exists){
console.log('exists:',exists);//true
});
node 0.8用fs.exists函数代替了path.exists函数。
fs模块
查询文件的统计信息(大小,创建时间等):
fs.stat('/etc/passwd',function(err,stats){
if(err){throw err;}
console.log(stats);//输出文件的元信息
stats.isFile();//如果是标准文件返回true
stats.isDirectory();//是目录返回true
stats.isBlockDevice();//块设备返回true
stats.isCharacterDevice();//字符设备
stats.isSymbolicLink();//符号链接
stats.isFifo();//FIFO
stats.isSocket();//套接字
});
打开文件并读取文件:
fs.open('/path/to/file','r',function(err,fd){
//文件描述符fd
if(err){throw err;}
var readBuffer = new Buffer(1024),
bufferOffset = 0,
bufferLength = readBuffer.length,
filePosition = 100;
fs.read(fd,readBuffer,bufferOffset,bufferLength,filePosition,
function read(err,readBytes){
if(err) {throw err;}
console.log('just read'+readBytes+'bytes');
if(readBytes>0)//如果等于0则代表到达文件结尾
console.log(readBuffer.slice(0,readBytes));
});
});
写入文件:
fs.open('./myfile.txt','a',function open(err,fd){
if(err){throw err;}
var writeBuffer = new Buffer("writing this string"),
bufferPosition=0,
bufferLength=writeBuffer.length,filePostion=null;
fs.write(fd,writeBuffer,bufferPosition,bufferLength,
filePosition//为null代表从当前文件的游标开始写入
function wrote(err,written){
console.log('wrote'+written+'bytes');
});
});
关闭文件只需调用fs.close(fd,[,callback])。
进程
执行外部命令
当需要执行一个外部shell或者可执行文件时,可以使用child_process模块。
var child_process = requier('child_process');
var exec = child_process.exec;
exec(command,function(err,stdout,stderr){...});//command为命令字符串
还可以再回调函数之前传入一个包含配置选项的可选参数。
var options = {
timeout:1000,//命令执行的超时时间
maxbuffer:1024,//stdout流和stderr流的最大容量,如果超过则子进程终止
killSignal:'SIGKILL',//如果超时或超过输出缓存容量,该信号就会被发送到子进程。
env:null;//传递给子进程的环境变量。默认为null.
}
父进程环境变量扩展:
var env = process.env,
varName,
envCopy={};
for(varName in env){
envCopy[varName] = env[varName];
}
//自定义变量
envCopy['custom1'] = 'some value';
...
生成子进程
使用exec()函数启动外部进程有如下缺点:
- 除了命令行参数和环境变量之外,不允许与子进程通信。
- 子进程的输出是被缓存的,无法对其流操作,可能会耗尽内存。
但是node会在父子进程之间创建一个双向通信通道,利用此通道发送字符串形式的数据或者强制终止子进程。
//使用child_process.spawn函数创建子进程
var spawn = require('child_process').spawn;
var child = spawn('tail',['-f','/var/log/system.log']);
//监听子进程的输出数据
child.stdout.on('data',function(data){...});
child.stderr.on('data',function(data){...});
向子进程发送数据
父进程想子进程的标准输入流中写入数据(childProcess.stdin)
子进程也可用process.stdin流来监听数据。但是先恢复流,因为默认情况下它属于暂停状态。
子进程child.js:
process.stdin.resume();
process.stdin.on('data',function(data){
var number = parseInt(data.toString(),10);
number+=1;
process.stdout.write(number+"\n");
});
父进程:
var child = spawn('node',['child.js']);
setInterval(function(){
var number = Math.floor(Math.random()*1000);
child.stdin.write(number+"\n");
child.stdout.once('data',function(data){
console.log(data);
});
});
监听子进程的退出:
child.on('exit',function(code){
console.log('child process terminated with code'+code);
});
发送信号终止进程
如果进程收到一个不知如何处理的信号,它就会终止。一些信号可以由子进程处理,一些信号只能由操作系统处理(例如SIGKILL,SIGSTOP)。可以使用child.kill()发送信号,默认是SIGTERM,也可传入信号参数。
var child = spawn('sleep',['10']);
setTimeout(function(){
child.kill();
},1000);
可以重写信号的默认行为:
child.kill('SIGUSR2');
//子进程
process.on('SIGUSR2',function(){console.log('got a sigusr2 signal';)});
流
创建文件系统流
var rs = fs.createReadStream('/path/file');
可以向此方法传递第二个参数options,包含几下选项:
encoding:data事件发送的字符串的编码格式
fd:如果已经有了一个打开文件描述符,则可传入。默认null.
bufferSize:要被读取的每个文件块的大小,默认64KB。
start:文件中第一个被读取的字节位置。
end:文件中最后一个被读取的字节位置。
创建一个文件可写流:
var rs = fs.createWriteStream('/path/to/file',options);
//options默认值如下:
{
flags:'w',//标志位
encoding:null,
mode:0666 //权限
}
避免慢客户端问题
大多数情况下,可以通过暂停数据生产者来避免填满具有未刷新缓冲区的内存(可读流)以便让消费者的数据(可写流)不会被传入核缓冲区。
require('http').createServer(function(req,res){
var rs = fs.createReadStream('/path/file');
rs.on('data',function(data){
if(!res.write(data)){
rs.pause();
}
});
res.on('drain',function(){
rs.resume();
});
rs.on('end',function(){
res.end();
});
}).listen(8080);
stream.pipe()
stream.pipe()方法实现了以上过程。由传输源调用,接收目标可写流作为第一个参数。
require('http').createServer(function(req,res){
var rs = fs.createReadStream('/path/file');
rs.pipe(res);
}).listen(8080);
默认情况下end()会在可读流结束时在可写流上调用。可以传入end:false自定义该行为。
rs.pipe(res);
rs.on('end',function(){
res.write('that is all');
res.end();
})
————————————————
版权声明:本文为CSDN博主「xiaoerjun」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiaoerjun/article/details/55803174