title: Node.js学习笔记(二)
date: 2017-10-09 15:58:32

Node.js核心模块之文件系统模块fs

fs(File System)是Node.js提供的对文件进行操作的模块,它提供了一组类似UNIX(POSIX)标准的文件操作API,这些模块中的方法均有异步和同步版本.利用fs模块,可以查询文件的统计信息/打开关闭文件/读写文件等.接下来介绍一些fs模块的常用功能:

  • 查询文件信息:fs.stat(path,callback)

    fs.stat()方法用于查询文件信息,可以用于查询文件的大小、创建时间、权限等相关信息。fs.stat()是异步方法,还有一个同步方法fs.statSync(path)。示例如下:
var fs = require('fs');
fs.stat('test.js', function (err, stats) {
    console.log(stats);
})

返回结果如下:

{ dev: 16777220,
mode: 33188,
nlink: 1,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 78808297,
size: 244,
blocks: 8,
atime: Wed May 27 2015 18:24:43 GMT+0800 (CST),
mtime: Wed May 27 2015 18:26:25 GMT+0800 (CST),
ctime: Wed May 27 2015 18:26:25 GMT+0800 (CST) }

fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:

var fs = require('fs');
fs.stat('test.js', function (err, stats) {
    console.log(stats.isFile());  //true
})

stats类中的方法有:

  • stats.isFile() 如果是标准文件,返回true。是目录、套接字、符号连接、或设备等返回false
  • stats. isDirectory() 如果是目录,返回true
  • stats. isBlockDevice() 如果是块设备,返回true,大多数情况下类UNIX系统的块设备都位于/dev目录下
  • stats. isCharacterDevice() 如果是字符设备,返回true
  • stats. isSymbolicLink() 如果是符号连接,返回true。(fs.lstat()方法返回的stats对象才有此方法)
  • stats.isFIFO() 如果是FIFO,返回true。FIFO是UNIX中的一种特殊类型的命令管道
  • stats. isSocket() 如果是UNIX套接字,返回true
  • 打开文件:fs.open(path, flags[, mode], callback)

    操作文件前需要选对文件进行打开操作。fs.open()方法用于打开文件,打开文件后,文件描述符fs会调用open方法的回调函数,然后就可以通过文件描述符fs对文件进行读写等操作了。同步版的方法名为fs.openSync(path, flags[, mode])。示例如下:
var fs = require('fs');
fs.open('./test/path.js', 'r', function (err, fd) {
    // 可以在这里通过文件描述fs对文件进行操作
});

fs.open()方法第一个参数是文件路径。每二个参数是标志位,标志位表示文件的打开模式。标志含义与UNIX中fopen的标识位相同:

  • r 打开文本文件进行读取,数据流位置在文件起始处
  • r+ 打开文本文件进行读写,数据流位置在文件起始处
  • w 如果文件存在,将其清零,不存在创建写入文件。数据流位置在文件起始处
  • w+ 打开文件进行读写,如果文件存在,将其清零,不存在创建写入文件。数据流位置在文件起始处
  • a 打开文件写入数据,如果文件存在,将其清零,不存在创建写入文件。数据流位置在文件结尾处,此后的写操作都将数据追加到文件后面
  • a+ 打开文件进行文件读写,如果文件存在,将其清零,不存在创建写入文件。数据流位置在文件结尾处,此后的写操作都将数据追加到文件后面
  • 读取文件信息:fs.read(fd, buffer, offset, length, position, callback)

    文件打开后,就可以使用fs.read()方法进行读取,在读取前需要一个文件描述符fd,创建文件描述符fd可以使用fs.open()方法.而后创建一个用于保存文件数据的缓冲区。缓冲区数据最终会被传递到回调函数中;
    从文件描述符fd中读取文件数据。
  • buffer是一个缓冲区,读取的数据将会写入到这里。
  • offset是开始向缓冲区 buffer 写入数据时的偏移量。
  • length是一个整型值,指定了读取的字节数。
  • position是一个整型值,指读取的文件起始位置,如果positionnull,将会从文件当前的位置读取数据。
  • callback中回调函数,其中包含了三个参数(err, bytesRead, buffer),分别表示:错误、读取的字节数、缓冲区。
    fs.read()方法可以实现部分文件内容的读取。通过lengthposition参数可以指定读取文件内容的长度和读取内容的起始位置。示例如下:
var fs = require('fs');
fs.open('./test/fs.js', 'r', function (err, fd) {
    var readBuffer = new Buffer(1024),
    offset = 0,
    len = readBuffer.length,
    filePostion = 100;
    fs.read(fd, readBuffer, offset, len, filePostion, function(err, readByte){
    console.log('读取数据总数:'+readByte+' bytes' );        
    // ==>读取数据总数:239 bytes
        console.log(readBuffer.slice(0, readByte));     //数据已被填充到readBuffer中
    })
});

上面的代码,文件打开后,会从第100个字节开始,读取其后的1024个字节的数据。读取完成后,fs.read()会回调最后一个回调方法,然后就可以可以处理读取到的的缓冲的数据了。

  • 读取文件信息(另一种方式): fs.readFile(filename[, options], callback)

    读取文件的全部内容:
  • filename要读取的文件。
  • options一个包含以下可选值的对象
    • encoding {String | Null} 默认:'utf8'
    • mode {Number} 默认:438 (aka 0666 in Octal)
    • flag {String} 默认:’w’
  • callback回调函数有2个参数 (err, data),参数 data 是文件的内容。如果没有指定参数encoding, 则返回值为Buffer。
    fs.readFile()方法能且只能读取文件的全部内容,通过设置编码方式可以以字符串或Buffer的形式返回读结果。
  • 将数据写入文件fs.write()

    fs.write()有以下两种形式,可以将一个buffer或data字符串写入到文件描述符fd指定的文件中。同样的在写入之前需要一个文件描述符fd,创建文件描述符fd,可以使用fs.open()方法
    fs.write(fd,buffer,offset,length[,position],callback)参数如下:
  • buffer是一个缓冲区,是要写入到文件的数据。
  • offset用于确认buffer写入数据时的偏移量。
  • length是一个整型值,指定写入数据的长度。
  • 通过offset和length可以确定buffer的哪个部分将会被写入文件。
  • position是一个整型值,指写入文件的起始位置,如果position为typeof position !== ‘number’,将会从文件当前的位置写入数据。
  • callback中回调函数,其中包含了三个参数(err, written, buffer),分别表示:错误、写入文件的字节数、缓冲区。
    fs.write(fd,data[,position[,encoding]],callback) 参数如下:
  • data要写入文件的字符串(当写入数据不是Buffer时,将会被转为字符串)。
  • position是一个整型值,指写入文件的起始位置,如果position为typeof position !== ‘number’,将会从文件当前的位置写入数据。
  • encoding指定写入字符串的编码方式。
  • callback中回调函数,其中包含了三个参数(err, written, buffer),分别表示:错误、写入文件的字节数、缓冲区。
    提示:fs.write()在没有等待回调而多次操作同一个文件是不安全的。在这种情况下,强烈推荐使用fs.createWriteStream()方法。
    文件打开后,可以通过 fs.write()方法传递一个数据缓冲区,以向打开的文件中写入数据。示例如下:
var fs = require('fs');

fs.open('./fs.txt', 'a', function (err, fd) {
    var writeBuffer = new Buffer('这是要写入的字符串'),
    offset = 0,
    len = writeBuffer.length,
    filePostion = null;

    fs.write(fd, writeBuffer, offset, len, filePostion, function(err, readByte){
    console.log('写数据总数:'+readByte+' bytes' );        
    // ==>写数据总数:27 bytes
    })
})

fs.writeSync()是fs.write()方法的同步版本。

  • 将数据写入文件(另一种方式):fs.writeFile(filename, data[, options], callback)

    将一个buffer或字符串写入到指定的文件中,当文件已经存在时,文件内容将会被替换。
  • filename要写入的文件。
  • data要写入的文件的数据,可以是一个buffer或字符串。
  • options一个包含以下可选值的对象
    • encoding {String | Null} ,写入数据的编码方式,默认:’utf8’。如果写入数据是buffer时,这个参数会被忽略。
    • mode {Number} 默认:438 (aka 0666 in Octal)
    • flag {String} 默认:’w’
      当写入数据是字符串时,options参数可以是一个字符串,表示字符串编码方式,如:’utf8’。
  • callback回调函数有1个参数 (err)。err, 表示可能出现的错误。
  • 文件、目录的重命名(移动) :fs.rename() fs.rename(oldPath, newPath, callback)

    这是异步版本的方法,此方法可以用于文件重命名和移动文件位置,此方法也可用于目录的操作。其回调函数中包含一个参数(err),该参数用于捕获可能出现的异常,当操作的文件或目录不存在、目标目录不存在等情况时会出现异常。
    示例:
fs.rename('./xxx.txt', '/tmp/world', function (err) {
    if (err) throw err;
    console.log('重命名完成');
})
  • 这是异步版本的方法,其回调函数中包含一个参数(err),该参数用于捕获可能出现的异常,当操作的文件不存在、操作的对象是目录等情况时会出现异常。
    示例:
fs.unlink('./itbilu.com.txt', function(err) {
    if (err) throw err;
    console.log('文件删除成功');
})
  • 目录的删除 fs.rmdir() fs.rmdir(paht,callback)

    fs.unlink()只能用于文件的删除,当需要删除目录时,需要使用fs.rmdir()方法。其回调函数中包含一个参数(err),该参数用于捕获可能出现的异常,当操作的目录不存在、操作的对象是文件、操作目录非空等情况时会出现异常。
    示例:
fs.rmdir('/tmp/itbaidu',function(err){
    if(err) throw err;
    console.log('目录删除成功');
})