fs模块小记<上>(周末我亦学,永远不脑瘫)

816 阅读5分钟

在学习fs之前首先我们得了解一些操作系统于文件的基础知识:

  • 权限位 mode
  • 标识位 flag
  • 描述符 fd
  1. 权限位mode

    简单介绍一下Linux的文件操作方面的知识:

    Linux系统上对文件的权限有着严格的控制,用于如果相对某个文件执行某种操作,必须具有对应的权限。

    Linux下文件的权限类型一般包括读,写,执行。对应字母为r、w、x。对应的数字表示为八进制数,具备权限的八进制数分别为 4(r) 、2(w)、1(x),不具备权限为 0(-)。

    Linux下权限的粒度有 拥有者 、群组 、其它组三种。

    每个文件都可以针对三个粒度,设置不同的rwx(读写执行)权限。 通常情况下,一个文件只能归属于一个用户和组,如果其它的用户想有这个文件的权限,则可以将该用户加入具备权限的群组,一个用户可以同时归属于多个组。

    Window的权限默认是可读、可写、不可执行,所以权限位数字表示为0o666,转换十进制表示为 438

    Linux上通常使用chmod命令对文件的权限进行设置和更改。

    为了更容易理解,我们可以随便在一个目录中打开 Git,使用 Linux 命令 ls -al 来查目录中文件和文件夹的权限位

    drwxr-xr-x 1 PandaShen 197121 0 Jun 28 14:41 core
    -rw-r--r-- 1 PandaShen 197121 293 Jun 23 17:44 index.md
    

    第一位代表是文件还是文件夹,d 开头代表文件夹,- 开头的代表文件,而后面九位就代表当前用户、用户所属组和其他用户的权限位,按每三位划分,分别代表读(r)、写(w)和执行(x),- 代表没有当前位对应的权限。

  2. 标识位 flag

    之前所说的权限位就是和标识位有着一些细微的关系。

    标识位就是意味着你对文件的操作方式。读写执行。

    flag 是不经常使用的,不容易被记住,所以在下面总结了一个加速记忆的方法。

    • r:读取
    • w:写入
    • s:同步
    • +:增加相反操作
    • x:排他方式

    r+ 和 w+ 的区别,当文件不存在时,r+ 不会创建文件,而会抛出异常,但 w+ 会创建文件;如果文件存在,r+ 不会自动清空文件,但 w+ 会自动把已有文件的内容清空。

  3. 描述符 fd

    操作系统会为每个打开的文件分配一个名为 文件描述符 的数值标识。

    在使用文件操作的时候,便是根据这个文件描述符去识别你在操作什么文件。

    Window 系统使用了一个不同但概念类似的机制来追踪资源,为方便用户,NodeJS抽象了不同操作系统间的差异,为所有打开的文件分配了数值的文件描述符。

    在 NodeJS 中,每操作一个文件,文件描述符是递增的,文件描述符一般从 3 开始。

    因为前面有 0、1、2三个比较特殊的描述符,分别代表 process.stdin(标准输入)、process.stdout(标准输出)和 process.stderr(错误输出)。

熟知了文件的一些基础之后,就可以进入node的文件模块学习时间。

  • 文件完整读/写

    什么是完整的读写?就是你一下扛一袋米上楼,不带喘气的。你就是完整的扛米,电脑呢就是完整的读写。一样的道理。
  1. 文件的读取

    fs.readFile(filename, [encoding], [callback(error,data)]
    
    • 第一个变量就是文件所在地点
    • 第二个第二个参数为 options,默认值为 null,其中有 encoding(编码,默认为 null)和 flag(标识位,默认为 r),也可直接传入 encoding;(不传就会读取buffer二进制数据)
    • 第三个就是回调函数 以下读取文件操作
    const fs = require('fs');
    //异步方法
    fs.readFile('./file/readFile.txt','utf8', function(err, data) {
        if (err) {
            throw err;
        }
        // 读取文件成功
        console.log(data);
    });
    //同步方法
    var data = fs.readFileSync('./file/readFile.txt','utf-8');
    console.log(data);
    
  2. 文件的写入

    fs.writeFile(filename, data, [options], callback)
    
    • 第一个参数为写入文件的路径或文件描述符;
    • 第二个参数为写入的数据,类型为 String 或 Buffer;
    • 第三个参数为 options,默认值为 null,其中有 encoding(编码,默认为 utf8)、 flag(标识位,默认为 w)和 mode(权限位,默认为 0o666),也可直接传入 encoding。
    encoding {String | null} default='utf-8'
    mode {Number} default=438(aka 0666 in Octal)
    flag {String} default='w' // w表示在写入之前清空原内容
    

    以下是一个例子

    const fs = require('fs');
    // 写入文件内容(如果文件不存在会创建一个文件)
    // 写入时会先清空文件
    fs.writeFile('./file/writeFile.txt', '写入成功:hello world', function(err) {
        if (err) {
            throw err;
        }
        // 写入成功后读取测试
        var data=fs.readFileSync('./file/writeFile.txt', 'utf-8');
        console.log('new data -->'+data);
    });
    
    // 数据追加
    setTimeout(function(){
    	// 追加
    	fs.writeFile('./file/writeFile.txt', '这里是追加的数据', {'flag':'a'},function(err) {
    	    if (err) {
    	        throw err;
    	    }
    	    console.log('success');
    	    var data=fs.readFileSync('./file/writeFile.txt', 'utf-8')
    	    // 写入成功后读取测试
    	    console.log('追加后的数据 -->'+data);
    	});
    },1000);
    
  3. 文件的追加写入

    当然,我们不可能每次写入都是清空了在写东西的,我们大多数时候都是喜欢在文件的末尾添加数据。例如你有一篇文档就差一句总结就完成了,我们就需要追加写入了。

    fs.appendFile(filename, data, [options], callback)
    
    • 第一个参数为写入文件的路径或文件描述符;
    • 第二个参数为写入的数据,类型为 String 或 Buffer;
    • 第三个参数为 options,默认值为 null,其中有 encoding(编码,默认为 utf8)、 flag(标识位,默认为 a)和 mode(权限位,默认为 0o666),也可直接传入 encoding。
    fs.appendFile("3.txt", " world", err => {
        if (!err) {
            fs.readFile("3.txt", "utf8", (err, data) => {
                console.log(data); // Hello world
            });
        }
    });
    
    fs.appendFileSync("3.txt", " world");
    let data = fs.readFileSync("3.txt", "utf8");
    
    console.log(data); // Hello world
    
  4. 文件的拷贝写入

        fs.copyFile(sourceFile, operationFile)
    
  • 第一个参数为被拷贝文件

  • 第二个参数为拷贝到的目标文件路径,如果目标文件不存在,则会创建并拷贝

    fs.copyFile("3.txt", "4.txt", () => {
        fs.readFile("4.txt", "utf8", (err, data) => {
            console.log(data); // Hello world
        });
    });
    
    function copy(src, dest) {
        let data = fs.readFileSync(src);
        fs.writeFileSync(dest, data);
    }
    copy("3.txt", "4.txt");
    let data = fs.readFileSync("4.txt", "utf8");
    console.log(data); // Hello world
    

以上便是fs模块的基础用法,下次将介绍一些高级的使用方法。