nodejs学习笔记2

路径操作

文件描述符句柄在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()函数启动外部进程有如下缺点:
1. 除了命令行参数和环境变量之外,不允许与子进程通信。
2. 子进程的输出是被缓存的,无法对其流操作,可能会耗尽内存。
但是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();
})
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值