在文件系统中,我们最常用到的就是文件的创建,读取,添加,删除等等,在nodejs中,有一个文件系统模块,在需要操作文件的时候 我们首先需要通过require方法引入这个文件系统模块。如下所示:
var fs=require('fs');
fs一些常见的操作
创建目录
//fs.mkdir(path, [mode], callback); /** * path, 被创建目录的完整路径及目录名; * [mode], 目录权限,默认0777 * [callback(err)], 创建完目录回调函数,err错误对象 */ fs.mkdir("./test",function (err) { if(err){ throw err; } console.log('创建目录成功') });
获取文件信息
//fs.stat(path, callback); /** * path, 要查看目录/文件的完整路径及名; * [callback(err, stats)], 操作完成回调函数;err错误对象,stat fs.Stat一个对象实例,提供如:isFile, isDirectory,isBlockDevice等方法及size,ctime,mtime等属性 */ fs.stat("./album",function (err,stats) { if(err) { throw err; } //判断是否是文件夹,如果是文件夹输出true if(stats.isDirectory()){ console.log(true); } });
读取目录
//使用fs.readdir读取目录,重点其回调函数中files对象 //fs.readdir(path, callback); /** * path, 要读取目录的完整路径及目录名; * [callback(err, files)], 读完目录回调函数;err错误对象,files数组,存放读取到的目录中的所有文件名 */ fs.readdir('./album',function (err,files) { if(err) { throw err; } console.log(files); });
读取文件readFile函数
//readFile(filename,[options],callback); /** * filename, 必选参数,文件名 * [options],可选参数,可指定flag(文件操作选项,如r+ 读写;w+ 读写,文件不存在则创建)及encoding属性 * callback 读取文件后的回调函数,参数默认第一个err,第二个data 数据 */ fs.readFile('./test.txt', function (err, data) { if(err) { console.error(err); return; } console.log(data); });
把异步变成同步
上面介绍的这些方法都是异步的方法,异步由于不会阻止后续代码的执行,所以有的时候,异步的方式会产生一些问题,如下实例:在该实例中,我们将读取一个目录,判断目录中的文件是不是一个文件夹,如果是一个文件夹,就输出,否则就跳过。解决这个问题的思路是,首先我们读取这个目录,得到这个目录中的所有文件,然后循环遍历得到的文件数组,依次判断文件是不是文件夹,如果是文件夹,就放入到我们事先定义的一个空数组中,循环完之后,我们输出这个数组。代码如下
var http=require("http"); var fs=require("fs"); var server=http.createServer(function (req,res) { if(req.url=="/favicon.ico"){ return; } /*读取文件*/ fs.readdir('./album',function (err,files) { if(err){ console.log(err) } var floderArr=[];//定义一个数组,如果是文件夹,就存放在该数组中 for(var i=0;i<files.length;i++){ /*读取文件信息*/ fs.stat('./album/'+files[i],function (err,stats) { if(stats.isDirectory()){ floderArr.push(files[i]); } }) } console.log(floderArr);//输出数组 }) res.end(); }); server.listen(3000,"127.0.0.1");
运行结果:
运行上述代码,我们发现,并没有按照我们预先想的,输出一个文件夹的数组,而是输出的一个空数组。这是因为,读取文件这个方法是异步的,他并不会等我们读取完文件再去执行输出数组的操作,而是一开始就回去输出这个数组,所以我们看到的就是输出一个空数组,解决这个问题的方式,我们要将这个方法变成同步的。解决方法如下:我们用一个自执行函数,然后读取完一个文件之后,然后再调用一次该函数,读取下一个文件,直到读取完所有的文件,再输出该数组
var http=require("http"); var fs=require("fs"); var server=http.createServer(function (req,res) { if(req.url=="/favicon.ico"){ return; } /*读取文件*/ fs.readdir('./album',function (err,files) { if(err){ console.log(err) } var floderArr=[]; (function isFloder(i) { if(i==files.length){ console.log(floderArr); return; } /*读取文件信息*/ fs.stat('./album/'+files[i],function (err,stats) { if(stats.isDirectory()){ floderArr.push(files[i]); } isFloder(i+1); }) })(0); }) res.end(); }); server.listen(3000,"127.0.0.1");
运行结果如下:
通过上面这种方式,我们就把一个异步的方法变成了一个同步的方法,这个案例只是提供一个解决问题的思路,实际上,fs提供了异步的文件操作方法,也提供了同步的文件方法,我们可以看实际需要,选择合适的方法。
静态资源文件管理
/** * Created by Danny on 2015/9/20 9:34. */ var http = require("http"); var fs = require("fs"); var url = require("url"); var path = require("path"); var server = http.createServer(function(req,res){ //这里如果不用req.url来if判断,那么用户不管输入什么网址, //做的事情都一样啊 //得到地址 var pathname = url.parse(req.url).pathname; //判断此时用户输入的地址是文件夹地址还是文件地址 //如果是文件夹地址,那么自动请求这个文件夹中的index.html if(pathname.indexOf(".") == -1){ pathname += "/index.html"; } //输入的网址是127.0.0.1/images/logo.png //实际请求的是./static/images/logo.png var fileURL = "./" + path.normalize("./static/" + pathname); //得到拓展名 var extname = path.extname(pathname); //把文件读出来 fs.readFile(fileURL,function(err,data){ //读完之后做的事情 if(err){ //文件不存在 res.writeHead(404,{"Content-Type":"text/html;charset=UTF8"}) res.end("404,页面没有找到"); } //读完之后做的事情 getMime(extname,function(mime){ res.writeHead(200,{"Content-Type":mime}) res.end(data); }); }); }); server.listen(80,"127.0.0.1"); function getMime(extname,callback){ //读取mime.json文件,得到JSON,根据extname key ,返回对应的value //读取文件 fs.readFile("./mime.json",function(err,data){ if(err){ throw Error("找不到mime.json文件!"); return; } //转成JSON var mimeJSON = JSON.parse(data); var mime = mimeJSON[extname] || "text/plain"; //执行回调函数,mime类型字符串,就是它的参数,因为readFile是一个异步的方法,所以这里需要用到回调函数,直接把操作写在回调里面 callback(mime); }); }