Outline

3 文件、进程、流和网络

  • 3.1 查询和读写文件
  • 3.2 创建和控制外部进程
  • 3.3 读写数据流

3 文件、进程、流和网络

3.1 查询和读写文件

path

从Node 0.8起,path模块只负责处理文件路径相关的字符串,不与实际文件或路径关联。

sample code:

/**
demonstration of module 'path' 's usage
*/
var path = require("path");

// 1 exists() - DEPRECATED use fs.exists("<path>", function(exists){}) instead
var fs = require("fs");
fs.exists("./path_demo.js", function(exists){// this file
  console.log(exists);
});
console.log(fs.existsSync("./path_demo.js"));// syn version

// 2 normalize()
console.log(path.normalize("/foo/bar/../baz"))

// 3 join()
var myPath = path.join("/foo", "bar", "..", "baz");
console.log(myPath);

// 4 resolve()
myPath = path.resolve("/hotdoc", "static_files/script", "../images/home.gif");
console.log(myPath);

// 5 relative()
myPath = path.relative("/data/test/aaa", "/data/src/aaa");
console.log(myPath);

// 6 dirname(), basename(), extname()
myPath = "/foo/bar/baz/index.html";
console.log("dirname="+path.dirname(myPath));
console.log("basename="+path.basename(myPath));
console.log("basename without extention="+path.basename(myPath, ".html"));
console.log("extname="+path.extname(myPath));

fs

fs模块用于查询文件的统计信息、文件的打开/读写/关闭等操作。

/**
demonstration of module 'fs''s usage,
files are put in $CWD/data
*/

var fs = require("fs");

// 1 stat()
fs.stat("./data/data.txt", function(error, stats){
  if(error){
    throw error;
  }
  console.log(stats);
  // hepler methods
  console.log("isFile="+stats.isFile());
  console.log("isDirectory="+stats.isDirectory());
  console.log("isBlockDevice="+stats.isBlockDevice());
  console.log("isCharacterDevice="+stats.isCharacterDevice());
  console.log("isSymbolicLink="+stats.isSymbolicLink());
  console.log("isFIFO="+stats.isFIFO());
  console.log("isSocket="+stats.isSocket());
});

// 2 open()
// 3 read()
fs.open("./data/data.txt", "r", function opened(error, fd){
  // fd: file descriptor
  if(error){ throw error; }

  var readBuffer = new Buffer(1024);
  fs.read(fd,
    readBuffer,
    0, // buffer's start position
    readBuffer.length,//data size
    0, // file postion
    function(error, readBytes){
      if(error) {throw error;}
      console.log("read "+ readBytes + " bytes");
      if(readBytes > 0){
        console.log(readBuffer.slice(0, readBytes).toString());
      }
    });

    fs.close(fd, function(){
      console.log("closed after read");
    });
});

// 4 write()
fs.open("./data/data.txt", "a", function(error, fd){// append mode
  if(error) {throw error;}

  var writeBuffer = new Buffer("this is the appended content");
  fs.write(fd,
    writeBuffer,
    0, // buffer's start position
    writeBuffer.length,// data size
    null, // current file's cursor
    function(error, writeBytes){
      if(error) {throw error;}
      console.log("write " + writeBytes + " bytes");
    }
  );

  fs.close(fd, function(){
    console.log("closed after write");
  });
});

// 5 close()
// default: file is closed when process end

3.2 创建和控制外部进程

(1) 执行外部进程

exec_external_cmd.js

/**
demonstration of execute external commands
*/

var exec = require("child_process").exec;
// execute "cat *.js | wc -l"
exec("cat *.js | wc -l", function(error, stdout, stderr){
  if(error){
    console.log("child process exited with error code: " + error.code);
    return;
  }
  console.log(stdout);//renderer the output of child process
});

// use configuration options
var options = {
  encoding: "utf8",
  timeout: 10000,
  killSignal: "SIGKILL",
  maxBuffer: 10 * 1024//default is 200*1024Bytes
};
exec("cat *.js | wc -c", options, function(error, stdout, stderr){
  if(error){
    console.log("child process exited with error code: " + error.code);
    return;
  }
  console.log(stdout);
});

// play with environment variables
// get this process's ENV
var env = process.env;
var envCopy = {};
for(var envVarname in env){
  envCopy[envVarname] = env[envVarname];// deep copy
}
envCopy["number"] = 123;// customed environment variable
exec("node child_env.js", {env: envCopy}, function(error, stdout, stderr){
  if(error) { throw error;}
  console.log("stdout:"+stdout);
  console.log("stderr:"+stderr);
});

child_env.js

/**
 a child process script to handle ENVs
*/
// ENV: number
var number = process.env.number;
console.log(typeof(number));// should be string

number = parseInt(number, 10);
console.log(typeof(number));

(2) 生成子进程

spawn_demo.js

/**
demonstration of spawn child processes
*/
var spawn = require("child_process").spawn;

// 1 spawn usage
// (1) not long-lived child process
// wc -l spawn_demo.js
//var child = spawn("wc", ["-l", "spawn_demo.js"]);

// (2) a long-lived child process
// tail -f spawn_demo.js
//var child = spawn("tail", ["-f", "spawn_demo.js"]);//this file

// (3) a sample IPC
/*
// node child_spawn.js
var child = spawn("node", ["child_spawn.js"]);
setInterval(function(){
  var number = Math.floor(Math.random() * 10000);

  // communicate to child process through FD stdin
  child.stdin.write(number+"\n");

  child.stdout.once("data", function(data){
    console.log("child's reply to " + number + " is " + data);
  });
}, 1000);
*/

// (4) child process killed by a singal
var child = spawn("sleep", ["5"]);

// 2 listen to child process's stdout
child.stdout.on("data", function(data){
  console.log("child output: "+ data);
});

child.stderr.on("data", function(data){
  console.log("child error output: " + data);
});

// listen to child process's exit
child.on("exit", function(code){
  console.log("child process exitd with code: " + code);
});

// listen to child process's exit with a returned signal
child.on("exit", function(code, signal){
  if(code){
    console.log("child process exitd with code: " + code);
  } else if(signal){
    console.log("child process killed by signal: " + signal);
  }
});

child_spawn_demo.js

/**
 demonstration of a spawnded child process to receive data from its stdin
*/

// unlock stream stdin's PAUSE state
process.stdin.resume();

process.stdin.on("data", function(data){
  var number;

  try{
    number = parseInt(data.toString(), 10);

    number += 1;

    // write to stdin
    process.stdout.write(number+"\n");
  } catch(error){
    process.stderr.write(err.message + "\n");
  }
});

(3) 进程间通信(IPC)

process_signal.js

/**
demonstration of sending signal to child process
*/
var spawn = require("child_process").spawn;

// [1]
//var child = spawn("sleep", ["10"]);

// [2]
var child = spawn("node", ["child_process_signal.js"]);

setTimeout(function(){
  // [1]
  // send a signal to child process: SIGTERM
  //child.kill();

  // [2]
  // send a signal to child process
  child.kill("SIGUSR2");
}, 3000);

// listeners
child.stdout.on("data", function(data){
  console.log("child stdout: " + data);
});

child.stderr.on("data", function(data){
  console.log("child stderr: " + data);
});

child.on("exit", function(code, signal){
  if(code){
    console.log("child process exitd with code: " + code);
  } else if(signal){
    console.log("child process killed by signal: " + signal);
  }
});

child_process_signal.js

/**
demonstration of process handle signals
*/
console.log("child process's pid="+process.pid);

var exec = require("child_process").exec;
exec("sleep 10", function(error, stdout, stderr){
  if(error){
    console.log("child process exited with error code: " + error.code);
    return;
  }
  console.log("stdout="+stdout);
  console.log("stderr="+stderr);
});

process.on("SIGUSR2", function(){
  console.log("incoming a SIGUSR2 singal, i will quit with killing myself");
  process.kill(process.pid);// kill self
});

3.3 读写数据流

文件流

可读read_stream.js

/**
demonstration of readable stream, including
events: data, end
method: pause(), resume()
*/
var fs = require("fs");

var options = {
  encoding: 'utf8',// null means will be Buffer in 'data' event, and  'utf8' means string
  fd: null, // an opened file descriptor
  bufferSize: 0,//size of file chunk
  start: 0, // start postion in file that want to read
  end:10 // end position in file that want to read
};
var readStream = fs.createReadStream("./data/data.txt", options);

readStream.on("data", function(data){
  console.log("type of data is : " + typeof(data));
  console.log(data.toString());
});

// pause the stream
readStream.pause();

// resume the paused stream
readStream.resume();

readStream.on("end", function(){
  console.log("the stream has ended");
})

可写write_stream.js

/**
demonstration of writeable stream, including
events: drain
method: write()
*/
var fs = require("fs");

var options = {
  flags: 'w',// same as fs.open()
  encoding: 'utf8',// same as readable buffer's options
  mode: 0666// file's priviledge
};
var writeStream = fs.createWriteStream("./data/data2.txt");

var inKernelOrQueue = writeStream.write("What is rational is real, and what is real is rational.");
// true means data has been sent to kernel's buffer,
// false means data had been save in queue in process's memory space
console.log("inKernelOrQueue="+inKernelOrQueue);

writeStream.on("drain", function(){
   console.log("data has been sent");
});

网络流

Socket是可读/可写流。
HTTP请求对象(request)是可读流,HTTP响应对象(response)是可写流。
具体内容见后面的模块说明。

慢客户端问题

典型场景:从可写流读,向可写流写入;但读的速度比写的速度快,需要可读流等待一下。

pipe_demo.js

/**
demonstration of readable stream's pipe() method,
it's used for handle write is more slow than read operation
*/
var http = require("http");
var fs = require("fs");

http.createServer(function(request, response){
  var readStream = fs.createReadStream("./data/data.txt");

  var options = {
    // true means the writeable stream's end() method will be called when the readable stream is end
    end: false
  };
  readStream.pipe(response, options);

  readStream.on("end", function(){
    response.write("that all the content");
    response.end();// directly call the end() method
  });

}).listen(8080);

Node.js高级编程读书笔记 - 2 文件和进程处理的更多相关文章

  1. Node.js高级编程读书笔记Outline

    Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...

  2. Node.js高级编程读书笔记 - 1 基本概念

    Outline 1 概述和安装 1.1 安装Node 1.2 Node简介 2 Node核心API基础 2.1 加载模块 2.2 应用缓冲区处理.编码和解码二进制数据 2.3 使用时间发射器模式简化事 ...

  3. Node.js高级编程读书笔记 - 6 应用程序构建和调试 - Never

    Explanation 现阶段console.log(...),util.inspect(...), JSON.stringify(...)在控制台输出已经够用了[2015/07/19]. 单元测试隶 ...

  4. Node.js高级编程读书笔记 - 4 构建Web应用程序

    Outline 5 构建Web应用程序 5.1 构建和使用HTTP中间件 5.2 用Express.js创建Web应用程序 5.3 使用Socket.IO创建通用的实时Web应用程序 5 构建Web应 ...

  5. Node.js高级编程读书笔记 - 3 网络编程

    Outline 3.4 构建TCP服务器 3.5 构建HTTP服务器 3.6 构建TCP客户端 3.7 创建HTTP请求 3.8 使用UDP 3.9 用TLS/SSL保证服务器的安全性 3.10 用H ...

  6. Node.js高级编程读书笔记 - 5 数据库 - Never

    Outline 6 连接数据库 6.1 使用node-mysql连接MySQL数据库 6.2 使用Nano连接CouchDB数据库 6.3 使用Mongoose连接MongoDB数据库 6 连接数据库 ...

  7. JS高级编程读书笔记

    导读:由于书的内容较多,内容划分也非常详尽,所以会分好几篇来写. 此页面仅作为跳转,权当个目录来用. 我会分块进行整理,大致如下: 第一章 简介 讲述javascript的历史,不打算整理,同学们大概 ...

  8. 《Node.js 高级编程》简介与第二章笔记

    <Node.js 高级编程> 作者简介 Pedro Teixerra 高产,开源项目程序员 Node 社区活跃成员,Node公司的创始人之一. 10岁开始编程,Visual Basic.C ...

  9. JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记2

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] JavaScript.jQuer ...

随机推荐

  1. 第九天 内容提供者 ContentResolver

    重点:理解ContentProvider 的作用和创建流程 1. 内容提供者,提供 其他数据库的访问. 特点       - 描述 : 它是android 四大组件之一,需要androidManife ...

  2. CentOS安装Nvidia显卡驱动提示Nouveau正在使用的问题

    如题,在安装Nvidia官方提供的驱动时,提示Nouveau正在被使用,需要停用后才能继续安装,在网上搜了不少方法,各种尝试后均无效. 最后通过设置内核启动参数给屏蔽了,方法如下: 切换到root用户 ...

  3. 移植linux-2.6.32.2到qq2440

    编译该版本内核使用的编译器版本:arm-linux-gcc 3.4.1 1.获取linux-2.6.32.2 2.解压内核 3.切换到刚解压的内核目录下: cd linux-2.6.32.2 4.修改 ...

  4. 自定义datagridview列,却提示DataGridView 控件中至少有一列没有单元格模板

    哈哈,一个小误区,你看看设计窗体生成的代码,DataGridView的列不是GridViewColumn 而是DataGridViewTextBoxColumn你只要添加这个类型的对象就可以了,我也是 ...

  5. 运行js提示库没有注册错误8002801d的解决办法

    运行js提示库没有注册错误8002801d的解决办法这个错误主要是因为服务器上的windows scripts版本较低,请按下面的链接下载较高版本windows scripts 5.6并在服务器上进行 ...

  6. Linux Vim不明原因卡死解决办法

    使用vim的时候,偶尔会碰到vim莫名其妙的僵在那里. 解决方案: 经查,原来Ctrl+S在Linux里是锁定屏幕的快捷键,如果要解锁,按下Ctrl+Q就可以了. 经验总结: 牢记这两个VIM组合键 ...

  7. quartz-2.2.x 快速入门 (1)

    欢迎来到quartz快速入门教程.阅读本教程,你将会了解: quartz下载 quartz安装 根据你的需要,配置Quartz 开始一个示例应用   当熟悉了quratz调度的基本功能后,可以尝试一些 ...

  8. 【C++】rand()函数,时间种子

    srand((unsigned)time(NULL)); //以时间为随机种子,写在循环前才有效(几个循环无所谓) ;i<=size;i++) { ;j<=size;j++) { ==ra ...

  9. 第十二章 非对称加密算法-RSA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 12.1.RSA(最经典的非对称加密算法) 特点: 使用一套密钥即可完成加解密(与D ...

  10. 在Linux中使用vi打开文件时如何显示行号,及跳转到指定行

    vi 文件名,打开文件后 如果要显示所有行号,使用 :set nu 如果要显示当前行号,使用 :nu 如果要跳转到指定行,使用 :行号 例如,跳转到第10行,使用 :10