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)
        });
    })
    
    
    
    
  • 相关阅读:
    jquery animate()方法 语法
    jquery unload方法 语法
    jquery undelegate()方法 语法
    jquery unbind()方法 语法
    jquery trigger() 方法 语法
    jquery toggle()方法 语法
    jquery change() 函数 语法
    jquery blur()函数 语法
    jquery bind()方法 语法
    jquery checked选择器 语法
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2264717.html
Copyright © 2011-2022 走看看