初学Node(五)文件I/O
文件读写
Node的出现的一个亮点就是让JS也有了读写文件的能力,而且实现起来要比其他语言更简单,对文件的一些操作我们都可通过fs模块来完成。fs即fileSystem的缩写,fs模块可以完成对文件的所有操作。
可以通过fs.readFileSync来同步的读取文件:
var fs = require("fs"); var data = fs.readFileSync("content.txt"); console.log(data.toString());
fs已经帮我们实现了一个读取文件的API,我们不用再像其他语言一样还要实例化IO对象,直接引入fs模块,调用readFileSync这个函数即可。
对文件的读取也可以通过fs.readFile(path,callback)来完成,这是一个异步的读取文件API,所以参数除了要读取的文件意外还需要一个读取完成的回调函数,相比同步读取,异步读取更加高效和实用:
var fs = require("fs"); fs.readFile("content.txt",function(err,data){ if(err){ return console.log(err.stack); } console.log("--文件读取成功--"); console.log(data.toString()); });
可以通过fs.writeFile来实现将内容写入到一个文件,如果文件已经错在就会改变里面的内容,如果不存在就创建然后在写入内容:
var fs = require("fs"); var data = "我是通过JS写入到文件的内容"; fs.writeFile("JSContent.txt",data,function(err){ if(err){ return console.log(err.stack); } console.log("文件写入完毕"); });
一个小demo测试读写文件的使用:
新建一个file文件夹,在里面新建新建一个template.html、head.txt、body.txt、foot.txt、demo.js:
template.html内容如下:
<body> {{head.txt}} {{body.txt}} {{foot.txt}} </body>
head.txt如下:
<h1>我是头部</h1>
body.txt如下:
<div>我是主体</div>
foot.txt如下:
<footer>我是尾部</footer>
demo.js如下:
var fs = require("fs");
fs.readFile("template.html",function(err,data){
if(err){
return console.log("读取文件错误");
}
var result = data.toString().replace(/{{\w*.\w*}}/g,function(one){
return fs.readFileSync(one.substring(2,one.length-2));
});
fs.writeFile("result.html",result,function(err){
if(err){
return console.log("生成文件错误");
}
console.log("生成文件成功");
});
});
我们在命令行中执行node.js就会生成一个正常的result.html文件了。
以流的方式来读写文件
利用流来读取文件:
var fs = require("fs"); var readStream = fs.createReadStream("content.txt"); readStream.setEncoding("UTF8"); readStream.on("data",function(data){ console.log(data); }); readStream.on("end",function(){ console.log("文件读取完毕"); }); readStream.on("error",function(err){ console.log("读取文件错误:"+err.stack); });
首先利用fs模块创建一个文件的读取流,然后设置读取内体的字符设置,读取流有三个事件分别为data,end,error,data即读取文件内容的时候,end即内容读取完毕时,error即读取文件发生错误时,我们可以为每一个事件定义对应的事件处理函数来完成我们的操作。
利用流来将内容写入文件:
var fs =require("fs"); var writeStream = fs.createWriteStream("content.txt"); writeStream.write("我是通过写入流写入的内容","UTF8"); writeStream.end(); writeStream.on("finish",function(){ console.log("文件写入成功"); }); writeStream.on("error",function(err){ console.log("写入文件时发生错误:"+err.stack); });
使用方式和读取流基本一致,不过事件换成了finish事件,表示文件写入成功时的事件,这个事件只有在调用end()函数之后才能被触发,end()表示内容已经写入完毕了。
当我们在实现一个复制文件的功能时,如果原始文件过大这个操作就会很耗时,此时我们就要利用管道流来优化这个过程,管道流在复制文件时并不会在将第一个文件的内容读取完毕后再写入目标文件,而是每读取一段内容就将这段内容写入到文件,然后在读在些一直到文件复制完毕:
var fs =require("fs"); var readStream = fs.createReadStream("content.txt"); var writeStream = fs.createWriteStream("result.txt"); readStream.pipe(writeStream); console.log("复制完成");
pipe函数就是我们所说的管道,我们可以把它看做是连接读取流和写入流的桥梁。