Skip to content

Instantly share code, notes, and snippets.

@LuoZijun
Created September 7, 2016 00:26
Show Gist options
  • Save LuoZijun/feb26eebef71e798a96a8e5e3adc6549 to your computer and use it in GitHub Desktop.
Save LuoZijun/feb26eebef71e798a96a8e5e3adc6549 to your computer and use it in GitHub Desktop.
Node JavaScript File I/O

NodeJS 解释器文件I/O (FILE I/O)

Date

09/07 2016

介绍

https://github.com/nodejs/node/blob/master/lib/fs.js

同步异步 用户JS代码样例:

// https://nodejs.org/api/fs.html
const fs = require('fs');

// ASYNC
fs.readFile('/etc/passwd', 'utf8', function (err, data){
    if (err) throw err;
    // File Content
    var content = data;
    console.log(content);
});

// SYNC
var content = fs.readFileSync('/etc/passwd', 'utf8');
console.log(content);

Node Lib 源码分析:

lib/fs.js :

// binding 为 Node JS 项目的模块管理系统,代表 和 `src/` 目录下面的 `C++` 代码函数绑定
const binding = process.binding('fs');

// ASYNC
fs.readFile = function(path, options, callback_) {
  // 注: 删掉了不必要的代码
  var context = new ReadFileContext(callback, encoding);
  context.isUserFd = isFd(path); // file descriptor ownership
  var req = new FSReqWrap();
  req.context = context;
  req.oncomplete = readFileAfterOpen;

  if (context.isUserFd) {
    process.nextTick(function() {
      req.oncomplete(null, path);
    });
    return;
  }
  // 绑定了 C++ `src/node_file.cc <https://github.com/nodejs/node/blob/master/src/node_file.cc>`_
  // 中的 `Open` 函数
  binding.open(pathModule._makeLong(path),
               stringToFlags(flag),
               0o666,
               req);
};

// SYNC
function tryReadSync(fd, isUserFd, buffer, pos, len) {
  // 注: 删掉了不必要的代码
  return fs.readSync(fd, buffer, pos, len);
}
fs.readSync = function(fd, buffer, offset, length, position) {
  // 注: 删掉了不必要的代码
  // 绑定了 C++ `src/node_file.cc <https://github.com/nodejs/node/blob/master/src/node_file.cc>`_
  // 中的 `Read` 函数
  var r = binding.read(fd, buffer, offset, length, position);
  var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
  return [str, r];
};
fs.readFileSync = function(path, options) {
  // 注: 删掉了不必要的代码
  var isUserFd = isFd(path); // file descriptor ownership
  var fd = isUserFd ? path : fs.openSync(path, flag, 0o666);
  var buffer = tryCreateBuffer(size, fd, isUserFd);
  tryReadSync(fd, isUserFd, buffer, pos, size - pos);
  return buffer;
};

现在简化JS代码:

// Sync
var r = binding.read(fd, buffer, offset, length, position);

// ASYNC
var ctx = new ReadFileContext(callback);
// https://github.com/nodejs/node/blob/master/lib/fs.js#L310
// ctx.read 方法为读取文件方法
// binding.read(this.fd, buffer, offset, length, -1, req); // 等价于同步模式

var req = new FSReqWrap(); // 绑定了 `C++` `src/node_file.cc` 当中的 `FSReqWrap` 类
req.context = ctx; // ctx.callback

binding.open(fd, flags, mode, req);
// `req` 为 `C++` `src/node_file.cc` 当中的 `FSReqWrap` 类
// `req` 实例里面把 用户传递进去的 `callback` 绑定在 `req` 实例中的 `oncomplete` 方法上(通过它来触发)

TODO:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment