nodejs 文本操作模块-fs模块

1. 首先是一类最常规的读写函数,函数名称和形式,应该是起源于C语言的。

1

2

3

4

5

6

fs.open(文件路径,读写标识,[文件mode值,666],回调函数(err,文件句柄fd));         

fs.read(文件句柄fd,被写入的buffer,offset,length,position,回调函数(err, bytesRead, buffer));         

fs.write(文件句柄fd,被读取的buffer,offset,length,position,回调函数(err,bytesWritten,buffer));         

fs.close(文件句柄,回调函数)         

fs.truncate(文件句柄,截断长度,回调函数);         

fs.fsync(文件句柄,回调函数);

 打开文件

1

2

3

4

5

6

7

8

9

10

11

12

// fs.open(filename, flags, [mode], callback);

/**

 * filename, 必选参数,文件名

 * flags, 操作标识,如"r",读方式打开

 * [mode],权限,如777,表示任何用户读写可执行

 * callback 打开文件后回调函数,参数默认第一个err,第二个fd为一个整数,表示打开文件返回的文件描述符,window中又称文件句柄

 */

fs.open(__dirname + '/test.txt''r''0666'function (err, fd) {

  console.log(fd);

});

  读文件,读取打开的文件内容到缓冲区中

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

//fs.read(fd, buffer, offset, length, position, callback);

/**

 * fd, 使用fs.open打开成功后返回的文件描述符

 * buffer, 一个Buffer对象,v8引擎分配的一段内存

 * offset, 整数,向缓存区中写入时的初始位置,以字节为单位

 * length, 整数,读取文件的长度

 * position, 整数,读取文件初始位置;文件大小以字节为单位

 * callback(err, bytesRead, buffer), 读取执行完成后回调函数,bytesRead实际读取字节数,被读取的缓存区对象

 */

fs.open(__dirname + '/test.txt''r'function (err, fd) {

  if(err) {

    console.error(err);

    return;

  else {

    var buffer = new Buffer(255);

    console.log(buffer.length);

    //每一个汉字utf8编码是3个字节,英文是1个字节

    fs.read(fd, buffer, 0, 9, 3, function (err, bytesRead, buffer) {

      if(err) {

        throw err;

      else {

        console.log(bytesRead);

        console.log(buffer.slice(0, bytesRead).toString());

        //读取完后,再使用fd读取时,基点是基于上次读取位置计算;

        fs.read(fd, buffer, 0, 9, nullfunction (err, bytesRead, buffer) {

          console.log(bytesRead);

          console.log(buffer.slice(0, bytesRead).toString());

        });

      }

    });

  }

});

  写文件,将缓冲区内数据写入使用fs.open打开的文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

//fs.write(fd, buffer, offset, length, position, callback);

/**

 * fd, 使用fs.open打开成功后返回的文件描述符

 * buffer, 一个Buffer对象,v8引擎分配的一段内存

 * offset, 整数,从缓存区中读取时的初始位置,以字节为单位

 * length, 整数,从缓存区中读取数据的字节数

 * position, 整数,写入文件初始位置;

 * callback(err, written, buffer), 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象

 */

fs.open(__dirname + '/test.txt''a'function (err, fd) {

  if(err) {

    console.error(err);

    return;

  else {

    var buffer = new Buffer('写入文件数据内容');

    //写入'入文件'三个字

    fs.write(fd, buffer, 3, 9, 12, function (err, written, buffer) {

      if(err) {

        console.log('写入文件失败');

        console.error(err);

        return;

      else {

        console.log(buffer.toString());

        //写入'数据内'三个字

        fs.write(fd, buffer, 12, 9, nullfunction (err, written, buffer) {

          console.log(buffer.toString());

        })

      }

    });

  }

});

// 使用fs.write写入文件时,操作系统是将数据读到内存,再把数据写入到文件中,当数据读完时并不代表数据已经写完,因为有一部分还可能在内在缓冲区内。

// 因此可以使用fs.fsync方法将内存中数据写入文件;--刷新内存缓冲区;

  刷新缓存区

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//fs.fsync(fd, [callback])

/**

 * fd, 使用fs.open打开成功后返回的文件描述符

 * [callback(err, written, buffer)], 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象

 */

fs.open(__dirname + '/test.txt''a'function (err, fd) {

  if(err)

    throw err;

  var buffer = new Buffer('我爱nodejs编程');

  fs.write(fd, buffer, 0, 9, 0, function (err, written, buffer) {

    console.log(written.toString());

    fs.write(fd, buffer, 9, buffer.length - 9, nullfunction (err, written) {

      console.log(written.toString());

      fs.fsync(fd);

      fs.close(fd);

    })

  });

});

  

2. 直接对文件进行读写的,用起来比较方便。

1

2

3

fs.readFile(文件名,编码,回调函数(err,data));      

fs.writeFile(文件名,数据,编码,回调函数(err));      

fs.appendFile(文件名,数据,编码,回调函数(err));

  读取文件readFile函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

//readFile(filename,[options],callback);

/**

 * filename, 必选参数,文件名

 * [options],可选参数,可指定flag(文件操作选项,如r+ 读写;w+ 读写,文件不存在则创建)及encoding属性

 * callback 读取文件后的回调函数,参数默认第一个err,第二个data 数据

 */

fs.readFile(__dirname + '/test.txt', {flag: 'r+', encoding: 'utf8'}, function (err, data) {

    if(err) {

     console.error(err);

     return;

    }

    console.log(data);

});

  写文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// fs.writeFile(filename,data,[options],callback);

var w_data = '这是一段通过fs.writeFile函数写入的内容;\r\n';

var w_data = new Buffer(w_data);

/**

 * filename, 必选参数,文件名

 * data, 写入的数据,可以字符或一个Buffer对象

 * [options],flag,mode(权限),encoding

 * callback 读取文件后的回调函数,参数默认第一个err,第二个data 数据

 */

fs.writeFile(__dirname + '/test.txt', w_data, {flag: 'a'}, function (err) {

   if(err) {

    console.error(err);

    else {

       console.log('写入成功');

    }

});

  以追加方式写文件

1

2

3

4

5

// fs.appendFile(filename,data,[options],callback);

fs.appendFile(__dirname + '/test.txt''使用fs.appendFile追加文件内容'function () {

  console.log('追加内容完成');

});

  

3. 其它常用文件操作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

判断文件是否存在     

fs.exists(文件路径,callback(是否存在));   <br>fs.existSync(文件路径); 同步执行;

重命名     

fs.rename(旧文件名,新文件名,回调函数);     

文件所有者变更     

fs.chown(文件名,uid,gid,回调函数);/fs.fchown(文件句柄fd,uid,gid,回调函数);/fs.lchown(链接路径,uid,gid,回调函数);     

文件权限变更     

fs.chmod(文件名,mode,回调函数);/fs.fchmod(文件句柄,mode,回调函数);/fs.lchmod(链接路径,mode,回调函数);     

文件信息     

fs.stat(文件路径,回调函数(err.fs.Stats对象));/fs.fstat(文件句柄fd,回调函数(err.fs.Stats对象));/fs.lstat(链接路径,回调函数(err.fs.Stats对象));     

文件时间     

fs.utimes(文件路径,访问时间,新建时间,回调函数);/fs.futimes(文件句柄,访问时间,新建时间,回调函数);     

监视文件     

fs.watchFile(文件名,[options],listener_callback(当前文件的stats,改变前的stats));     

fs.unwatchFile(文件名);

  查看文件与目录的是否存在

1

2

3

4

5

6

7

8

9

10

11

//fs.exists(path, callback);

/**

 * path, 要查看目录/文件的完整路径及名;

 * [callback(exists)], 操作完成回调函数;exists true存在,false表示不存在

 */

fs.exists(__dirname + '/te'function (exists) {

  var retTxt = exists ? retTxt = '文件存在' '文件不存在';

  console.log(retTxt);

});

  修改文件访问时间与修改时间

1

2

3

4

5

6

7

8

9

10

11

12

13

14

//fs.rename(oldPath, newPath, callback);

/**

 * oldPath, 原目录/文件的完整路径及名;

 * newPath, 新目录/文件的完整路径及名;如果新路径与原路径相同,而只文件名不同,则是重命名

 * [callback(err)], 操作完成回调函数;err操作失败对象

 */

fs.rename(__dirname + '/test', __dirname + '/fsDir'function (err) {

  if(err) {

    console.error(err);

    return;

  }

  console.log('重命名成功')

});

  修改文件或目录的操作权限

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

//fs.chmod(path, mode, callback);

/**

 * path, 要查看目录/文件的完整路径及名;

 * mode, 指定权限,如:0666 8进制,权限:所有用户可读、写,

 * [callback(err)], 操作完成回调函数;err操作失败对象

 */

fs.chmod(__dirname + '/fsDir', 0666, function (err) {

  if(err) {

    console.error(err);

    return;

  }

  console.log('修改权限成功')

});

  查看文件与目录的信息

1

2

3

4

5

6

7

8

//fs.stat(path, callback);

//fs.lstat(path, callback); //查看符号链接文件

/**

 * path, 要查看目录/文件的完整路径及名;

 * [callback(err, stats)], 操作完成回调函数;err错误对象,stat fs.Stat一个对象实例,提供如:isFile, isDirectory,isBlockDevice等方法及size,ctime,mtime等属性

 */

//实例,查看fs.readdir

  修改文件访问时间与修改时间

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//fs.utimes(path, atime, mtime, callback);

/**

 * path, 要查看目录/文件的完整路径及名;

 * atime, 新的访问时间

 * ctime, 新的修改时间

 * [callback(err)], 操作完成回调函数;err操作失败对象

 */

fs.utimes(__dirname + '/test.txt'new Date(), new Date(), function (err) {

  if(err) {

    console.error(err);

    return;

  }

  fs.stat(__dirname + '/test.txt'function (err, stat) {

    console.log('访问时间: ' + stat.atime.toString() + '; \n修改时间:' + stat.mtime);

    console.log(stat.mode);

  })

});

  

4. 目录操作

1

2

3

fs.mkdir(路径,权限mode/777,回调函数);   

fs.rmdir(路径,回调函数);   

fs.readdir(路径,回调函数(err,fileNameArray));

 

  创建目录

1

2

3

4

5

6

7

8

9

10

11

12

13

14

//使用fs.mkdir创建目录

//fs.mkdir(path, [mode], callback);

/**

 * path, 被创建目录的完整路径及目录名;

 * [mode], 目录权限,默认0777

 * [callback(err)], 创建完目录回调函数,err错误对象

 */

fs.mkdir(__dirname + '/fsDir'function (err) {

  if(err)

    throw err;

  console.log('创建目录成功')

});

  读取目录

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

//使用fs.readdir读取目录,重点其回调函数中files对象

//fs.readdir(path, callback);

/**

 * path, 要读取目录的完整路径及目录名;

 * [callback(err, files)], 读完目录回调函数;err错误对象,files数组,存放读取到的目录中的所有文件名

 */

fs.readdir(__dirname + '/fsDir/'function (err, files) {

  if(err) {

    console.error(err);

    return;

  else {

    files.forEach(function (file) {

      var filePath = path.normalize(__dirname + '/fsDir/' + file);

      fs.stat(filePath, function (err, stat) {

        if(stat.isFile()) {

          console.log(filePath + ' is: ' 'file');

        }

        if(stat.isDirectory()) {

          console.log(filePath + ' is: ' 'dir');

        }

      });

    });

    for (var i = 0; i < files.length; i++) {

      //使用闭包无法保证读取文件的顺序与数组中保存的致

      (function () {

        var filePath = path.normalize(__dirname + '/fsDir/' + files[i]);

        fs.stat(filePath, function (err, stat) {

          if(stat.isFile()) {

            console.log(filePath + ' is: ' 'file');

          }

          if(stat.isDirectory()) {

            console.log(filePath + ' is: ' 'dir');

          }

        });

      })();

    }

  }

});

  删除目录

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//fs.rmdir(path, callback);

/**

 * path, 目录的完整路径及目录名;

 * [callback(err)], 操作完成回调函数;err操作失败对象

 */

fs.rmdir(__dirname + '/test'function (err) {

  fs.mkdir(__dirname + '/test', 0666, function (err) {

    console.log('创建test目录');

  });

  if(err) {

    console.log('删除空目录失败,可能原因:1、目录不存在,2、目录不为空')

    console.error(err);

    return;

  }

  console.log('删除空目录成功!');

});

  

5. 链接文件操作

1

2

3

4

5

6

7

8

创建一个链接  

fs.link(srcpath, dstpath, [callback])  

fs.symlink(destination, path, [type], [callback]) 

  

读取链接指向的路径  

fs.readlink(path, [callback(err,linkstr)])  

fs.unlink(path,[callback]);

  

6.监视文件 
 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//对文件进行监视,并且在监视到文件被修改时执行处理

//fs.watchFile(filename, [options], listener);

/**

 * filename, 完整路径及文件名;

 * [options], persistent true表示持续监视,不退出程序;interval 单位毫秒,表示每隔多少毫秒监视一次文件

 * listener, 文件发生变化时回调,有两个参数:curr为一个fs.Stat对象,被修改后文件,prev,一个fs.Stat对象,表示修改前对象

 */

fs.watchFile(__dirname + '/test.txt', {interval: 20}, function (curr, prev) {

  if(Date.parse(prev.ctime) == 0) {

    console.log('文件被创建!');

  else if(Date.parse(curr.ctime) == 0) {

    console.log('文件被删除!')

  else if(Date.parse(curr.mtime) != Date.parse(prev.mtime)) {

    console.log('文件有修改');

  }

});

fs.watchFile(__dirname + '/test.txt'function (curr, prev) {

  console.log('这是第二个watch,监视到文件有修改');

});

  

7、取消监视文件

1

2

3

4

5

6

7

8

9

10

11

12

//取消对文件进行监视

//fs.unwatchFile(filename, [listener]);

/**

 * filename, 完整路径及文件名;

 * [listener], 要取消的监听器事件,如果不指定,则取消所有监听处理事件

 */

var listener = function (curr, prev) {

  console.log('我是监视函数')

}

fs.unwatchFile(__dirname + '/test.txt', listener);

  

8、监视文件或目录

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// 对文件或目录进行监视,并且在监视到修改时执行处理;

// fs.watch返回一个fs.FSWatcher对象,拥有一个close方法,用于停止watch操作;

// 当fs.watch有文件变化时,会触发fs.FSWatcher对象的change(err, filename)事件,err错误对象,filename发生变化的文件名

// fs.watch(filename, [options], [listener]);

/**

 * filename, 完整路径及文件名或目录名;

 * [listener(event, filename], 监听器事件,有两个参数:event 为rename表示指定的文件或目录中有重命名、删除或移动操作或change表示有修改,filename表示发生变化的文件路径

 */

var fsWatcher = fs.watch(__dirname + '/test'function (event, filename) {

  //console.log(event)

});

//console.log(fsWatcher instanceof FSWatcher);

fsWatcher.on('change'function (event, filename) {

  console.log(filename + ' 发生变化')

});

//30秒后关闭监视

setTimeout(function () {

  console.log('关闭')

  fsWatcher.close(function (err) {

    if(err) {

      console.error(err)

    }

    console.log('关闭watch')

  });

}, 30000);

  

9、文件流

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

/*

 * 流,在应用程序中表示一组有序的、有起点有终点的字节数据的传输手段;

 * Node.js中实现了stream.Readable/stream.Writeable接口的对象进行流数据读写;以上接口都继承自EventEmitter类,因此在读/写流不同状态时,触发不同事件;

 * 关于流读取:Node.js不断将文件一小块内容读入缓冲区,再从缓冲区中读取内容;

 * 关于流写入:Node.js不断将流数据写入内在缓冲区,待缓冲区满后再将缓冲区写入到文件中;重复上面操作直到要写入内容写写完;

 * readFile、read、writeFile、write都是将整个文件放入内存而再操作,而则是文件一部分数据一部分数据操作;

 *

 * -----------------------流读取-------------------------------------

 * 读取数据对象:

 * fs.ReadStream 读取文件

 * http.IncomingMessage 客户端请求或服务器端响应

 * net.Socket    Socket端口对象

 * child.stdout  子进程标准输出

 * child.stdin   子进程标准入

 * process.stdin 用于创建进程标准输入流

 * Gzip、Deflate、DeflateRaw   数据压缩

 *

 * 触发事件:

 * readable  数据可读时

 * data      数据读取后

 * end       数据读取完成时

 * error     数据读取错误时

 * close     关闭流对象时

 *

 * 读取数据的对象操作方法:

 * read      读取数据方法

 * setEncoding   设置读取数据的编

 * pause     通知对象众目停止触发data事件

 * resume    通知对象恢复触发data事件

 * pipe      设置数据通道,将读入流数据接入写入流;

 * unpipe    取消通道

 * unshift   当流数据绑定一个解析器时,此方法取消解析器

 *

 * ------------------------流写入-------------------------------------

 * 写数据对象:

 * fs.WriteStream           写入文件对象

 * http.clientRequest       写入HTTP客户端请求数据

 * http.ServerResponse      写入HTTP服务器端响应数据

 * net.Socket               读写TCP流或UNIX流,需要connection事件传递给用户

 * child.stdout             子进程标准输出

 * child.stdin              子进程标准入

 * Gzip、Deflate、DeflateRaw  数据压缩

 *

 * 写入数据触发事件:

 * drain            当write方法返回false时,表示缓存区中已经输出到目标对象中,可以继续写入数据到缓存区

 * finish           当end方法调用,全部数据写入完成

 * pipe             当用于读取数据的对象的pipe方法被调用时

 * unpipe           当unpipe方法被调用

 * error            当发生错误

 *

 * 写入数据方法:

 * write            用于写入数据

 * end              结束写入,之后再写入会报错;

 */

  

10、创建读取流

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

//fs.createReadStream(path, [options])

/**

 * path 文件路径

 * [options] flags:指定文件操作,默认'r',读操作;encoding,指定读取流编码;autoClose, 是否读取完成后自动关闭,默认true;start指定文件开始读取位置;end指定文件开始读结束位置

 */

var rs = fs.createReadStream(__dirname + '/test.txt', {start: 0, end: 2});

  //open是ReadStream对象中表示文件打开时事件,

rs.on('open'function (fd) {

  console.log('开始读取文件');

});

rs.on('data'function (data) {

  console.log(data.toString());

});

rs.on('end'function () {

  console.log('读取文件结束')

});

rs.on('close'function () {

  console.log('文件关闭');

});

rs.on('error'function (err) {

  console.error(err);

});

//暂停和回复文件读取;

rs.on('open'function () {

  console.log('开始读取文件');

});

rs.pause();

rs.on('data'function (data) {

  console.log(data.toString());

});

setTimeout(function () {

  rs.resume();

}, 2000);

  

11、创建写入流

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

//fs.createWriteStream(path, [options])

/**

 * path 文件路径

 * [options] flags:指定文件操作,默认'w',;encoding,指定读取流编码;start指定写入文件的位置

 */

/* ws.write(chunk, [encoding], [callback]);

 * chunk,  可以为Buffer对象或一个字符串,要写入的数据

 * [encoding],  编码

 * [callback],  写入后回调

 */

/* ws.end([chunk], [encoding], [callback]);

 * [chunk],  要写入的数据

 * [encoding],  编码

 * [callback],  写入后回调

 */

var ws = fs.createWriteStream(__dirname + '/test.txt', {start: 0});

var buffer = new Buffer('我也喜欢你');

ws.write(buffer, 'utf8'function (err, buffer) {

  console.log(arguments);

  console.log('写入完成,回调函数没有参数')

});

//最后再写入的内容

ws.end('再见');

//使用流完成复制文件操作

var rs = fs.createReadStream(__dirname + '/test.txt')

var ws = fs.createWriteStream(__dirname + '/test/test.txt');

rs.on('data'function (data) {

  ws.write(data)

});

ws.on('open'function (fd) {

  console.log('要写入的数据文件已经打开,文件描述符是: ' + fd);

});

rs.on('end'function () {

  console.log('文件读取完成');

  ws.end('完成'function () {

    console.log('文件全部写入完成')

  });

});

//关于WriteStream对象的write方法返回一个布尔类型,当缓存区中数据全部写满时,返回false;

//表示缓存区写满,并将立即输出到目标对象中

//第一个例子

var ws = fs.createWriteStream(__dirname + '/test/test.txt');

for (var i = 0; i < 10000; i++) {

  var w_flag = ws.write(i.toString());

  //当缓存区写满时,输出false

  console.log(w_flag);

}

//第二个例子

var ws = fs.createWriteStream(__dirname + '/test/untiyou.mp3');

var rs = fs.createReadStream(__dirname + '/test/Until You.mp3');

rs.on('data'function (data) {

  var flag = ws.write(data);

  console.log(flag);

});

//系统缓存区数据已经全部输出触发drain事件

ws.on('drain'function () {

  console.log('系统缓存区数据已经全部输出。')

});

  

12、管道pipe实现流读写

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

//rs.pipe(destination, [options]);

/**

 * destination 必须一个可写入流数据对象

 * [opations] end 默认为true,表示读取完成立即关闭文件;

 */

var rs = fs.createReadStream(__dirname + '/test/Until You.mp3');

var ws = fs.createWriteStream(__dirname + '/test/untiyou.mp3');

rs.pipe(ws);

rs.on('data'function (data) {

  console.log('数据可读')

});

rs.on('end'function () {

  console.log('文件读取完成');

  //ws.end('再见')

});

猜你喜欢

转载自blog.csdn.net/liudongdong19/article/details/81352501