您的位置:首页 > Web前端 > Node.js

node.js 文件系统模块 - fs

2020-08-25 15:04 1111 查看

node.js 文件系统模块 - fs

fs 模块简要说明

fs 模块提供了用于与文件系统进行交互(以类似于标准 POSIX 函数的方式)的 API。

  • 导入 fs 模块
    const fs = require('fs');

所有的文件系统操作API都具有同步和异步的形式。

  1. 异步的形式总是把完成回调作为其最后一个参数。 传给完成回调的参数取决于具体方法,但第一个参数总是预留给异常。 如果操作被成功地完成,则第一个参数会为 null 或 undefined。

    const fs = require('fs');
    // unlink 用于异步删除文件
    fs.unlink('文件', (err) => {
    if (err) throw err;
    console.log('已成功地删除文件');
    });
    
  2. 当使用同步的操作时,发生的异常会被立即地抛出,可以使用 try…catch 处理,也可以冒泡。

    const fs = require('fs');
    try {
    // unlinkSync 用于同步删除文件
    fs.unlinkSync('文件');
    console.log('已成功地删除文件');
    } catch (err) {
    // 处理错误
    }
    

    建议大家使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。

fs 模块常用方法讲解

fs.open - 打开文件

fs.open(path[, flags[, mode]], callback)

  • path - 文件的路径。

  • flags - 文件打开的方式。

  • mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。

  • callback - 回调函数,有两个参数 (err, fd)。fd 是返回的文件描述符。

  • flags 参数值参考下表:

    flag 描述
    r 以读取模式打开文件。如果文件不存在抛出异常。
    r+ 以读写模式打开文件。如果文件不存在抛出异常。
    rs 以同步的方式读取文件。
    rs+ 以同步的方式读取和写入文件。
    w 以写入模式打开文件,如果文件不存在则创建。
    wx 类似 ‘w’,但是如果文件路径存在,则文件写入失败。
    w+ 以读写模式打开文件,如果文件不存在则创建。
    wx+ 类似 ‘w+’, 但是如果文件路径存在,则文件读写失败。
    a 以追加模式打开文件,如果文件不存在则创建。
    ax 类似 ‘a’, 但是如果文件路径存在,则文件追加失败。
    a+ 以读取追加模式打开文件,如果文件不存在则创建。
    ax+ 类似 ‘a+’, 但是如果文件路径存在,则文件读取追加失败。

    案例:

    // 异步的打开文件
    fs.open('demo.txt', 'r', (err, fd) => {
    if (err){
    // 不用return的话,下面的代码会继续执行
    return console.error(err);
    }
    
    console.log('文件打开成功!');
    })

fs.close - 关闭文件

fs.close(fd, callback)

  • fd - 通过 fs.open() 方法返回的文件描述符。

  • callback - 回调函数,没有参数。

    案例:

    // 异步的打开文件
    fs.open('demo.txt', 'r', (err, fd) => {
    if (err){
    // 不用return的话,下面的代码会继续执行
    return console.error(err);
    }
    
    console.log('文件打开成功!');
    
    // 异步的关闭文件
    fs.close(fd, function(err){
    if (err){
    throw err;
    }
    console.log("文件关闭成功");
    });
    })

fs.read - 使用文件描述符来读取文件

fs.read(fd, buffer, offset, length, position, callback)

  • fd - 通过 fs.open() 方法返回的文件描述符。

  • buffer - 数据写入的缓冲区。

  • offset - 缓冲区写入的写入偏移量。

  • length - 要从文件中读取的字节数。

  • position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。

  • callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。

    案例:

    const fs = require('fs');
    var buf = new Buffer.alloc(1024);
    
    console.log("准备打开文件!");
    fs.open('demo.txt', 'r+', function(err, fd) {
    if (err) {
    return console.error(err);
    }
    console.log("文件打开成功!");
    console.log("准备读取文件!");
    fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
    if (err){
    console.log(err);
    }
    
    // 仅输出读取的字节
    if(bytes > 0){
    console.log(buf.slice(0, bytes).toString());
    }
    
    // 关闭文件
    fs.close(fd, function(err){
    if (err){
    console.log(err);
    }
    console.log("文件关闭成功");
    });
    });
    });
    
    out:
    准备打开文件!
    文件打开成功!
    准备读取文件!
    这里是demo.txt中的内容!
    文件关闭成功
    

fs.readFile - 读取小文件(异步地读取文件的全部内容。)

fs.readFile(path[, options], callback)

  • path - 文件名或文件描述符。

  • options

    encoding - 编码格式,默认值: null。

  • flag - 文件打来方式。默认值: ‘r’。

    如果没有指定字符编码,则返回原始的 buffer。
    如果 options 是字符串,则它指定字符编码。

  • callback

      err - 读取失败返回 err 信息

    • data - 读取成功返回 data

    案例:

    fs.readFile('demo.txt', "utf-8", (err, data) => {
    if (err) {
    return console.error(err);
    }
    
    console.log(`读取到文件:${data}`);
    })
    
    out:
    读取到文件:这里是demo.txt中的内容!

    fs.createReadStream - 读取大文件(流式读取)

    fs.readFile() 函数会缓冲整个文件。 若要最小化内存成本,则尽可能选择流式(使用 fs.createReadStream())。

    可以参考 node.js stream 这篇文章

    fs.createReadStream(path[, options])

    • path - 文件路径。

    • options

      flags - 文件打来方式。默认值: ‘r’。

    • encoding - 编码格式。默认值: null。

    • fd - 文件描述符,默认值: null。

    • mode - 文件模式,默认值: 0o666。

    • autoClose - 默认值: true。

      如果 autoClose 为 false,则即使发生错误,文件描述符也不会被关闭。 应用程序需要负责关闭它并确保没有文件描述符泄漏。 如果 autoClose 被设置为 true(默认的行为),则当 ‘error’ 或 ‘end’ 事件时,文件描述符会被自动地关闭。

    • emitClose - 默认值: false。

      默认情况下,流被销毁之后不会触发 ‘close’ 事件。 这与其他 Readable 流的默认设置是相反的。 设置 emitClose 选项为 true 可以更改此行为。

    • start - 开始读取的位置

    • end - 结束读取的位置,默认值: Infinity。

      start 和 end 值,用于从文件中读取一定范围的字节,而不是读取整个文件。

    • highWaterMark - 设置readable stream的缓冲区的大小, 默认值: 64 * 1024,以字节为单位。

    • fs - 重写对应的 fs 实现(用于 open、 read 和 close)。默认值: null。

    案例:

    const fs = require('fs');
    // demo.txt中内容:this is a demo
    const file = fs.createReadStream('./demo.txt', {
    flags: 'r', // 文件的操作方式,默认是 r
    encoding: 'utf-8', // 编码格式
    start: 0, // 开始读取的位置
    end: 6, // 结束读取的位置
    highWaterMark: 1 // 每次读取的个数, 以字节为单位, 默认值64 * 1024字节
    });
    
    // 每当从流中读取到数据时就会触发 data 事件
    file.on('data', chuck => {
    console.log(`读到数据---${chuck}`);
    });
    
    // close事件在流关闭后触发,这里故意和 end 事件调换了定义的顺序,观察结果会不会发生变化
    file.on('close', () => {
    console.log('读取流已经关闭');
    });
    
    // end 事件在数据读取完成时才会触发
    file.on('end', () => {
    console.log('已经读取完成');
    });
    
    // 必须为 error 事件添加监听器,否则程序在遇到异常时会终止运行
    file.on('error', err => {
    console.error(err);
    });
    
    out:
    读到数据---t
    读到数据---h
    读到数据---i
    读到数据---s
    读到数据---
    读到数据---i
    读到数据---s
    已经读取完成
    读取流已经关闭
    

    fs.writeFile - 写入数据

    fs.writeFile(file, data[, options], callback)

    • file - 文件名或文件描述符。

    • data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(缓冲) 对象。

    • options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 ‘w’。也可以是一个单独的字符串,表示编码格式。

    • callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。

      案例:

      const fs = require('fs');
      fs.writeFile('demo.txt', '这是要写入的数据!','utf-8', err => {
      if (err) {
      return console.error(err);
      }
      
      console.log('写入成功');
      });
      

      不等待回调就对同一个文件多次使用 fs.writeFile() 是不安全的。 对于这种情况,建议使用 fs.createWriteStream()。

    fs.createWriteStream - 写入数据(流式写入)

    可以参考 node.js stream 这篇文章

    fs.createWriteStream(path[, options])

    • path - 文件路径

    • options

      flags - 文件打来方式。默认值: ‘w’。

    • encoding - 编码格式。默认值: ‘utf8’。

    • fd - 文件描述符,默认值: null。

    • mode - 文件模式,默认值: 0o666。

    • autoClose 默认值: true。

      如果 autoClose 被设置为 true(默认的行为),则当 ‘error’ 或 ‘finish’ 事件时,文件描述符会被自动地关闭。 如果 autoClose 为 false,则即使发生错误,文件描述符也不会被关闭。 应用程序需要负责关闭它并确保没有文件描述符泄漏。

    • emitClose 默认值: false。

      默认情况下,流被销毁之后不会触发 ‘close’ 事件。 这与其他 Writable 流的默认设置是相反的。 设置 emitClose 选项为 true 可以更改此行为。

    • start - 开始写入的位置。

      start 选项,用于写入数据到文件开头之后的某个位置,

    • highWaterMark - 设置writable stream的缓冲区的大小。

      如果需要设置writable stream的缓冲区的大小,那么在创建流的时候,需要设置opts.highWaterMark,这样如果缓冲区里的数据超过opts.highWaterMark,.write(data)方法会返回false。当缓冲区可写的时候,writable stream会触发’drain’ 事件。

    • fs - 重写对应的 fs 实现(用于 open、 read 和 close)。默认值: null。

    案例:

    const fs = require('fs');
    const file = fs.createWriteStream('./demo01.txt', {
    flags: 'w',  // 操作方式,默认是 w
    encoding: 'utf-8',  // 编码格式
    start: 0,  // 在文件中开始写入的位置
    highWaterMark: 3  // 缓冲区大小, 一般不需要配置
    });
    
    let f = file.write('a', 'utf-8', () => {
    console.log("写入数据a");
    });
    
    console.log(f);
    
    f = file.write('bb', 'utf-8', () => {
    console.log("写入数据bb");
    });
    
    console.log(f);
    
    // 标记文件末尾
    file.end();
    
    // end 方法执行完成才会触发 finish 事件
    file.on('finish', () => {
    console.log("全部数据写入完成");
    })
    
    // 必须为 error 事件添加监听器,否则程序在遇到异常时会终止运行
    file.on('error', err => {
    console.error(err);
    })
    
    out:
    true
    false
    写入数据a
    写入数据bb
    全部数据写入完成
    

    fs.stat - 获取文件信息

    fs.stat(path, callback)

    • path - 文件路径。

    • callback - 回调函数,有两个参数 (err, stats),其中 stats 是 fs.Stats 对象。

    • fs.Stats 对象的方法:

      flag 描述
      stats.isFile() 如果是文件返回 true,否则返回 false。
      stats.isDirectory() 如果是目录返回 true,否则返回 false。
      stats.isBlockDevice() 如果是块设备返回 true,否则返回 false。
      stats.isCharacterDevice() 如果是字符设备返回 true,否则返回 false。
      stats.isSymbolicLink() 如果是软链接返回 true,否则返回 false。
      stats.isFIFO() 如果是FIFO,返回true,否则返回 false。FIFO是UNIX中的一种特殊类型的命令管道。
      stats.isSocket() 如果是 Socket 返回 true,否则返回 false。

      案例:

      // 通过异步模式获取文件信息
      fs.stat('demo.txt', (err, stats) => {
      if (err){
      return console.error(err);
      }
      
      console.log("是否为文件(isFile) ? " + stats.isFile());
      console.log("是否为目录(isDirectory) ? " + stats.isDirectory());
      });
      
      out:
      是否为文件(isFile) ? true
      是否为目录(isDirectory) ? false

    fs.unlink - 删除文件

    fs.unlink(path, callback)

    • path - 文件路径。

    • callback - 回调函数,没有参数。

      案例:

      // 异步的删除文件
      fs.unlink('./1.txt', (err) => {
      if (err) throw err;
      console.log('成功删除文件!');
      })

    fs.mkdir - 创建目录

    fs.mkdir(path[, options], callback)

    • path - 文件路径。

    • options 参数可以是:

      recursive - 是否以递归的方式创建目录,默认为 false。

    • mode - 设置目录权限,默认为 0777。

  • callback - 回调函数,没有参数。

    案例:

    // 创建 `./目录1/目录2/目录3`,不管 `/目录1` 和 `/目录1/目录2` 是否存在。
    fs.mkdir('./目录1/目录2/目录3', { recursive: true }, (err) => {
    if (err) throw err;
    });
  • fs.readdir - 读取目录

    fs.readdir(path[, options], callback)

    • path - 文件路径。

    • options

      encoding - 编码格式,默认值: ‘utf8’。

    • withFileTypes - files 数组是否包含 fs.Dirent 对象。默认值: false。

      如果 options.withFileTypes 被设置为 true,则 files 数组会包含 fs.Dirent 对象。

  • callback - 回调函数

      err - 错误信息。

    • files - 目录下的文件数组列表。

  • fs.Dirent 对象的方法:

    flag 描述
    dirent.isFile() 如果是文件返回 true,否则返回 false。
    dirent.isDirectory() 如果是目录返回 true,否则返回 false。
    dirent.isBlockDevice() 如果是块设备返回 true,否则返回 false。
    dirent.isCharacterDevice() 如果是字符设备返回 true,否则返回 false。
    dirent.isSymbolicLink() 如果是软链接返回 true,否则返回 false。
    dirent.isFIFO() 如果是FIFO,返回true,否则返回 false。FIFO是UNIX中的一种特殊类型的命令管道。
    dirent.isSocket() 如果是 Socket 返回 true,否则返回 false。

    案例:

    // 异步的读取目录内容
    fs.readdir('node_modules', {withFileTypes: true},(err, files) => {
    if (err) {
    throw err;
    }
    
    // 打印 files 数组
    console.log(files);
    
    // options.withFileTypes 被设置为 true,则 files 数组会包含 fs.Dirent 对象
    files.forEach(val => {
    console.log(`${val.name} 是文件吗?`, val.isFile());
    console.log(`${val.name} 是目录吗?`, val.isDirectory());
    })
    })
    
    out:
    [
    Dirent { name: '.bin', [Symbol(type)]: 2 },
    Dirent { name: 'accepts', [Symbol(type)]: 2 },
    ]
    
    .bin 是文件吗? false
    .bin 是目录吗? true
    accepts 是文件吗? false
    accepts 是目录吗? true
  • fs.rmdir - 删除目录

    fs.rmdir(path, callback)

    • path - 文件路径。

    • callback - 回调函数,除了可能的异常 err,没有其他参数。

      案例:

      目录结构:
      
      - demo   // demo目录
      demo.txt   // 文件夹中有一个demo.txt文件
      main.js   // 主程序
      
      fs.rmdir('./a', err => {
      if (err) {
      return console.error(err);
      }
      
      console.log('删除成功!');
      })
      
      out:
      [Error: ENOTEMPTY: directory not empty, rmdir 'E:\workspace\node\a'] {
      errno: -4051,
      code: 'ENOTEMPTY',
      syscall: 'rmdir',
      path: 'E:\\workspace\\node\\a'
      }

      出错的原因是demo目录下还有一个文件,rmdir函数最好用来删除空目录。

    fs 还有很多其他的API可用,在使用时可以参考 官方文档:http://nodejs.cn/api/fs.html#fs_file_system

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: