Node.js文件基本操作
关于Node.js的文件操作,首先我们从利用Node.js实现文件拷贝的例子说起:
1 2 3 4 5
| var fs = require('fs'); function copyFile(src, dist){ fs.writeFileSync(dist, fs.readFileSync(src)); } copyFile('./test.txt','./testcopy.txt');
|
上述代码实现了,在当前的js同级目录下,复制text.txt文件内容到textcopy.txt文件中。对于小文件,我们可以这么实现拷贝。但当文件较大时,这样通过一次性读取文件内容到内存,再一次性写入磁盘,就有问题了。对于大文件的拷贝,我们通过下面的方式实现。
1 2 3 4 5 6
| var fs = require('fs'); function copyFile(src, dist){ // fs.createWriteStream(dist).p(dist, fs.readFileSync(src)); fs.createReadStream(src).pipe(fs.createWriteStream(dist)); } copyFile('./info.txt', './copyinfo.txt');
|
上述代码实现的是,边读边写,这样一点一点儿的实现大文件的拷贝。
Node.js的fs模块为我们操作文件提供了查询和操作函数。
查询文件统计信息
利用fs.stat方法查询文件或目录的元信息。
1 2 3 4 5
| var fs = require('fs'); fs.stat('./info.txt', function(err, stats){ if(err) throw err; console.log(stats); })
|
控制台的输出为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { dev: 16777218, mode: 33188, nlink: 1, uid: 501, gid: 20, rdev: 0, blksize: 4096, ino: 11999814, size: 3360, blocks: 8, atime: Sun Sep 18 2016 15:40:41 GMT+0800 (CST), mtime: Sun Sep 18 2016 15:13:30 GMT+0800 (CST), ctime: Sun Sep 18 2016 15:13:30 GMT+0800 (CST), birthtime: Tue Sep 06 2016 18:38:47 GMT+0800 (CST) }
|
fs.stat()函数调用会将stats类的一个实例传递给回调函数,这个实例可调用一下方法:
1 stats.isFile():如果是标准文件,返回true
2 stats.isDirectory(): 如果是目录,返回true
3 stats.isBlockDevice(): 如果是块设备,返回true
4 stats.isCharacterDevice(): 如果是字符设备,返回true
5 stats.isSymbolicLink(): 如果是符号链接,返回true
6 stats.isFifo(): 如果是FIFO,返回true
7 stats.isSocket(): 如果是UNIX套接字,返回true
(ps: 除了前两个,后面的都有些 懵逼.jpg,待后续再补充。)
打开文件
fs.open方法,用来打开文件,然后使用文件描述符调用回调函数。
1 2 3 4
| var fs = require('fs'); fs.open('./test.txt', 'r', function(err, fd){ //处理操作 })
|
第一个参数为文件路径,第二个参数为标志位,文件以哪种模式打开(r, r+, w, w+, a, a+:加号的区别在于,读写操作是否都具备)。
1 r:打开文本文件进行读取,数据流的位置在文件的起始处
2 r+:打开文件进行读写,数据流的位置在文件起始处
3 w:如果文件存在,将其清空,如果不存在,就创建文件写入数据,数据流位置在文件起始处
4 w+:打开文件进行读写,如果文件不粗安在就创建它,如果存在,将文件清零,数据流的位置在文件起始处
5 a:打开文件写入数据,如果文件不存在就创建,如果存在就将文件清零,数据流的位置在文件的结尾处,此后的写操作将数据追加到文件后面
6 a+:打开文件进行读写,如果文件不存在就创建,如果存在就将文件清零,数据流的位置在文件的结尾处,此后的写操作将数据追加到文件后面
读取文件
1 2 3 4 5 6 7 8 9 10 11 12
| var fs = require('fs'); fs.open('./app.js','r+', function(err, 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(err, readBytes){ if(err) throw err; console.log('just read ' + readBytes + ' bytes') }) })
|
一旦将缓冲区传递给fs.open()函数,缓冲区的控制权就转交给了read命令,只有在回调函数被调用之后,缓冲区的控制权才会返还给你。在此之前不应该对缓冲区进行读写或让其他函数调用该缓冲区,否则则可能会读取不完整的数据,更糟糕的情况可能会并发地往该缓冲区中写入数据。
写入数据
通过fs.write()函数传递一个包含数据的缓冲区,可以向一个已打开的文件中写入数据。
1 2 3 4 5 6 7 8 9 10 11 12
| var fs = require('fs'); fs.open('./info.txt','a', function(err, fd){ if(err) throw err; var writeBuffer = new Buffer('测试写入数据'), bufferOffset = 0, bufferLength = writeBuffer.length, filePosition = null; fs.write(fd, writeBuffer, bufferOffset, bufferLength, filePosition, function(err, writeBytes){ if(err) throw err; console.log('write ' + writeBytes + ' bytes') }) })
|
传递给缓冲区包含以下一些信息:
1 准备写入的缓冲区的数据
2 待写入数据在缓冲区的起始位置
3 待写入数据的长度
4 从文件中的什么位置开始写入数据
5 写入文件操作结束后被调用的回调函数
在上述例子中,项文件中写入数据的起始位置为null,标明写入操作将当前文件的游标处开始。由于是以追加模式打开文件的,因此此时文件的游标位于文件的结尾处。
关闭文件
在实际应用程序中,一旦打开某个文件,最后就必须关闭它。为此,必须跟踪那些已经打开的文件的描述符,在最后不再需要它们的时候,使用fs.close(fd[,callback])关闭它们。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var fs = require('fs'); fs.open('./info.txt','a', function(err, fd){ if(err) throw err; function notifyErr(err){ fs.close(fd, function(){ console.log('关闭文档')}); } var writeBuffer = new Buffer('测试写入数据'), bufferOffset = 0, bufferLength = writeBuffer.length, filePosition = null; fs.write(fd, writeBuffer, bufferOffset, bufferLength, filePosition, function(err, writeBytes){ if(err) return notifyErr(err); fs.close(fd, function(){ console.log('读写完毕,关闭文档')}); console.log('write ' + writeBytes + ' bytes'); }) })
|