zoukankan      html  css  js  c++  java
  • node.js 文件操作

    既然到了后台,只要你有权限就可以为所欲为了!

    创建文件夹

    //fs.js
    var fs = require('fs');
    fs.mkdirSync('a', 0755);
    fs.mkdirSync('a/b', 0755);
    fs.mkdirSync('a/b/c', 0755);
    

    那么它会在fs.js所在目录中创建一个a目录,a目录下再创建b目录,b目录下创建c目录。mkdirSync是一个同步方法,拥有三个参数,第一个是路径,第二个是目录权限,第三个是回调

    但这样做有点不妥,如果指定目录已存在,就报错。如果要建立多级目录,一层层判定此目录是否存在,立即会陷入“回调地狱”的境地。虽然node.js对于IO操作的方法都提供了两个版本,一个是同步的,一个是异步的。想了想,搞出我自己的mkdirSync函数,实现比mkdirp的作者好很多。

    
    
    var fs = require('fs');
    
    function mkdirSync(url,mode,cb){
        var path = require("path"), arr = url.split("/");
        mode = mode || 0755;
        cb = cb || function(){};
        if(arr[0]==="."){//处理 ./aaa
            arr.shift();
        }
        if(arr[0] == ".."){//处理 ../ddd/d
            arr.splice(0,2,arr[0]+"/"+arr[1])
        }
        function inner(cur){
            if(!path.existsSync(cur)){//不存在就创建一个
                fs.mkdirSync(cur, mode)
            }
            if(arr.length){
                inner(cur + "/"+arr.shift());
            }else{
                cb();
            }
        }
        arr.length && inner(arr.shift());
    }
    //测试代码
    mkdirSync("aaa/ddd/dd",0,function(e){
        if(e){
            console.log('出错了');
        }else{
            console.log("创建成功")
        }
    });
    

    有关目录的创建的讨论,详见这里

    创建文件与写入内容

    创建文件的方法fs.open(path, flags, [mode], [callback])好像所有语言都很一致,可能是想与最原始的C语言的方法保持一致。这是个异步方法,其同步版本,与其他同步方法一样,就是少了个回调。说一下flags中w与a的不同,w会把已存在的同名文件删除再创建一个,因此要注意。

    fs.open("test.txt", "w");
    

    写入内容。这有几种方法,比如fs.write,不过它的第一个参数要求类型为Buffer,而fs.openSync不是返回一个Buffer,因此它不能与fs.write配合使用。

    //fs.js
    var fs = require('fs');
    
    fs.open("test.txt","w",0644,function(e,fd){
        if(e) throw e;
        fs.write(fd,"first fs!",0,'utf8',function(e){
            if(e) throw e;
            fs.closeSync(fd);
        })
    });
    

    这时,我们就创建一个文本文件,里面写入"first fs"。不过open中间那两个参数的不是必要的。我们可以再搞一个fs2.js脚本

    //fs2.js
    var fs = require('fs');
    fs.open("test.txt","a",0644,function(e,fd){
        if(e) throw e;
        fs.write(fd,"second fs!",function(e){
            if(e) throw e;
            fs.closeSync(fd);
        })
    });
    

    执行它,它会在test.txt追加"second fs"这句话。

    fs的open, write, close有点像我们在浏览器对document的操作。此外,还有fs.writeFile与fs.writeFileSync,可惜它们不能做追加内容的操作。

    
    var fs = require('fs');
    
    fs.writeFile("test.txt","third fs!",function(e){//会先清空原先的内容
        if(e) throw e;
    })
    
    

    删除目录或文件

    var fs = require('fs');
    fs.rmdir("aaa",function(e){
        if(e){
            console.log(e)
        }
    })
    /**
    { stack: [Getter/Setter],
      arguments: undefined,
      type: undefined,
      message: 'ENOTEMPTY, Directory not empty \'aaa\'',
      errno: 39,
      code: 'ENOTEMPTY',
      path: 'aaa' }
    */
    

    报错,缘由是之前我们还为aaa创建了子目录,必须逐个删除,实在不人性化,于是又造了一个轮子。

    var fs = require('fs');
    
    var rmdirSync = (function(){
        function iterator(url,dirs){
            var stat = fs.statSync(url);
            if(stat.isDirectory()){
                dirs.unshift(url);//收集目录
                inner(url,dirs);
            }else if(stat.isFile()){
                fs.unlinkSync(url);//直接删除文件
            }
        }
        function inner(path,dirs){
            var arr = fs.readdirSync(path);
            for(var i = 0, el ; el = arr[i++];){
                iterator(path+"/"+el,dirs);
            }
        }
        return function(dir,cb){
            cb = cb || function(){};
            var dirs = [];
    
            try{
                iterator(dir,dirs);
                for(var i = 0, el ; el = dirs[i++];){
                    fs.rmdirSync(el);//一次性删除所有收集到的目录
                }
                cb()
            }catch(e){//如果文件或目录本来就不存在,fs.statSync会报错,不过我们还是当成没有异常发生
                e.code === "ENOENT" ? cb() : cb(e);
            }
        }
    })();
    
    rmdirSync("aaa",function(e){
        console.log("!!!"+e)
        console.log("删除aaa目录以及子目录成功")
    })
    
    

    上面的rmdirSync还可以分解出一个方法,取得给定目录下的所有目录与文件。

    var fs = require('fs');
    var getAllFolersAndFiles = (function(){
        function iterator(url, folders, files){
            var stat = fs.statSync(url);
            if(stat.isDirectory()){
                folders.unshift(url);//收集目录
                inner(url,folders, files);
            }else if(stat.isFile()){
                files.unshift(url);//收集文件
            }
        }
        function inner(path,folders,files){
            var arr = fs.readdirSync(path);
            for(var i = 0, el ; el = arr[i++];){
                iterator(path+"/"+el,folders,files);
            }
        }
        return function(dir){
            var folders = [], files = [];
            try{
                iterator(dir,folders,files);
            }catch(e){
            }finally{
                return {
                    folders : folders,
                    files   : files
                }
            }
        }
    })()
    

    如果我们只想取得指定目下的所有文件,还可以更精简些!

    function getAllFiles(root) {
      var result = [], files = fs.readdirSync(root)
      files.forEach(function(file) {
        var pathname = root+ "/" + file
          , stat = fs.lstatSync(pathname)
        if (stat === undefined) return
    
        // 不是文件夹就是文件
        if (!stat.isDirectory()) {
          result.push(pathname)
        // 递归自身
        } else {
          result = result.concat(getAllFiles(pathname))
        }
      });
      return result
    }
    

    监听文件的改动

    就是使用watchFile及其同步版本。

    var fs = require("fs"),
    sys = require("util");
    fs.open("aaa.js","w",0644,function(e,fd){
        fs.writeSync(fd,"console.log(1111);");
        fs.closeSync(fd);
    })
    
    fs.watchFile("aaa.js", function(curr, prev) {
      sys.puts("\n\ttest_file.txt has been edited");
      sys.puts("\tThe current mtime is: " + curr.mtime);
      sys.puts("\tThe previous mtime was: " + prev.mtime + "\n");
    });
    
    fs.open("aaa.js","a",0644,function(e,fd){
        fs.writeSync(fd,"console.log(2222)");
        fs.closeSync(fd);
    });
    

    此外,node.js还提供了修改了目录文件权限的操作,但这些都是不值一提。自己看看文档就会了。

    //合并脚本
    var fs = require("fs")
    var path = require("path") //不同的操作系统,其 文件目录 分割符是不一样的,不能直接使用 + "/"来实现
    var curDir = process.cwd() //当前目录
    var otherDir = curDir.replace(/avalon[\/\\]src/, "")
    console.log("otherDir " + otherDir)
    var Buffer = require('buffer').Buffer
    var now = new Date
    var date = now.getFullYear() + "." + now.getMonth() + "." + now.getDate()
    function directive(name) {
        return path.join("15 directive", name)
    }
    //avalon.js 所需要合并的子文件
    var compatibleFiles = [
        "00 inter", "01 variable", "01 variable.share", "02 core", "03 es5.shim",
        "04 dom.polyfill", "05 configuration", "06 EventBus", "06 findNodes",
        "07 modelFactory", "07 modelFactory.shim", "08 Collection", "09 dispatcher",
        "10 HTML", "12 scan", "12 scanTag", "12 scanNode", "12 scanAttr", "12 scanText",
        "13 dom", "14 parser", "14 parser.share",
        directive("skip"), directive("controller"), directive("important"),
        directive("attr"), directive("include"), directive("class.hover.active"), directive("data"),
        directive("text"), directive("html"), directive("if"), directive("visible"), directive("on"),
        directive("widget"), directive("duplex.1"), directive("duplex.2"),
        directive("duplex.3"), directive("repeat.each.with"),
        "16 filter", "17 loader", "18 domReady", "19 outer"
    ]
    //avalon.modern.js 所需要合并的子文件
    var modernFiles = [
        "00 inter", "01 variable.modern", "01 variable.share", "02 core.modern",
        "04 dom.polyfill.modern", "05 configuration", "06 EventBus", "06 findNodes.modern",
        "07 modelFactory", "08 Collection", "09 dispatcher", "10 HTML.modern",
        "12 scan", "12 scanTag", "12 scanNode", "12 scanAttr.modern", "12 scanText",
        "13 dom.modern", "14 parser.modern", "14 parser.share",
        directive("skip"), directive("controller"), directive("important"),
        directive("attr"), directive("include"), directive("class.hover.active"), directive("data"),
        directive("text.modern"), directive("html"), directive("if"), directive("visible"), directive("on"),
        directive("widget"), directive("duplex.1"), directive("duplex.2.modern"),
        directive("duplex.3"), directive("repeat.each.with"),
        "16 filter", "17 loader", "18 domReady.modern", "19 outer"
    ]
    //avalon.shim.js 所需要合并的子文件
    var shimFiles = [
        "00 inter", "01 variable", "01 variable.share", "02 core", "03 es5.shim",
        "04 dom.polyfill", "05 configuration", "06 EventBus", "06 findNodes",
        "07 modelFactory", "07 modelFactory.shim", "08 Collection", "09 dispatcher",
        "10 HTML", "12 scan", "12 scanTag", "12 scanNode", "12 scanAttr", "12 scanText",
        "13 dom", "14 parser", "14 parser.share",
        directive("skip"), directive("controller"), directive("important"),
        directive("attr"), directive("include"), directive("class.hover.active"), directive("data"),
        directive("text"), directive("html"), directive("if"), directive("visible"), directive("on"),
        directive("widget"), directive("duplex.1"), directive("duplex.2"),
        directive("duplex.3"), directive("repeat.each.with"),
        "16 filter", "18 domReady.noop", "19 outer"
    ]
    var writable = fs.createWriteStream(path.join(curDir, 'avalon.js'), {
        encoding: "utf8"
    });
    writable.setMaxListeners(100) //默认只有添加11个事件,很容易爆栈
    
    compatibleFiles.forEach(function(fileName) {
        var filePath = path.join(curDir, fileName + ".js")
        var readable = fs.createReadStream(filePath)
        if (fileName == "00 inter") {
            readable.on('data', function(chunk) {
                var str = chunk.toString("utf8")
                var offset = (new Buffer(str.slice(0, str.indexOf("!!")), "utf8")).length
                chunk.write(" build in " + date + " \n", offset)
            })
        }
        //  readable.push("//都会插到新文件的最前面")
        //  writable.write("//都会插到新文件的最前面 ")
        readable.pipe(writable)
        readable.on("readable", function() {
            writable.write("\n")
            console.log("add " + filePath)
        })
        //更新avalon.test中的文件
        writable.on("finish", function() {
            var readable3 = fs.createReadStream(path.join(curDir, 'avalon.js'))
            var writable3 = fs.createWriteStream(path.join(otherDir, 'avalon.test', "src", "avalon.js"))
            readable3.pipe(writable3)
        });
    })
    var writable2 = fs.createWriteStream(path.join(curDir, 'avalon.modern.js'), {
        encoding: "utf8"
    })
    writable2.setMaxListeners(100) //默认只有添加11个事件,很容易爆栈
    
    modernFiles.forEach(function(fileName) {
        var filePath = path.join(curDir, fileName + ".js")
        var readable = fs.createReadStream(filePath)
        if (fileName == "00 inter") {
            readable.on('data', function(chunk) {
                var str = chunk.toString("utf8")
                var offset = (new Buffer(str.slice(0, str.indexOf("!!")), "utf8")).length
                chunk.write(" build in " + date + " \n", offset)
            })
        }
        //  readable.push("//都会插到新文件的最前面")
        //  writable.write("//都会插到新文件的最前面 ")
        readable.pipe(writable2)
        readable.on("readable", function() {
            writable2.write("\n")
            console.log("add " + filePath)
        })
        //更新avalon.test中的文件
        writable2.on("finish", function() {
            var readable3 = fs.createReadStream(path.join(curDir, 'avalon.modern.js'))
            var writable3 = fs.createWriteStream(path.join(otherDir, 'avalon.test', "src", "avalon.modern.js"))
            readable3.pipe(writable3)
        });
    })
    
    
    
    
  • 相关阅读:
    服务器常用端口
    xml处理类
    水印的代码
    Asp.net常用的51个代码(非常实用)
    poj 2453
    MOD
    LIS(最长上升子序列)
    POJ各题算法分类(转)
    poj 1496&1850
    poj 1423
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2264717.html
Copyright © 2011-2022 走看看