[Nodejs] node的fs模块
fs 模块
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作 API。 Node 导入文件系统模块(fs)。Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。最好使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞(重点)。对于流量较大的服务器,最好还是采用异步操作,同步操作时,只有前一个操作结束,才会开始后一个操作,如果某个操作特别耗时(常常发生在读写数据时),会导致整个程序停顿
常用方法
| 操作 | 异步方法 | 同步方法 | 
|---|---|---|
| 打开文件 | fs.open(path, flags[, mode], callback) | fs.openSync(path, flags[, mode]) | 
| 文件信息 | fs.stat(path[, options], callback) | fs.statSync(path[, options]) | 
| 新建文件 | fs.appendFile(path, data[, options], callback) | fs.appendFileSync(path, data[, options]) | 
| 写入文件 | fs.writeFile(file, data[, options], callback) | fs.writeFileSync(file, data[, options]) | 
| 读取文件 | fs.read() | |
| 读取文件 | fs.readFile(path[, options], callback) | fs.readFileSync(path[, options]) | 
| 重命名文件 | fs.rename(oldPath, newPath, callback) | fs.renameSync(oldPath, newPath) | 
| 关闭文件 | fs.close(fd, callback) | fs.closeSync(fd) | 
| 截取文件 | fs.ftruncate(fd[, len], callback) | fs.ftruncateSync(fd[, len]) | 
| 删除文件 | fs.unlink(path, callback) | fs.unlinkSync(path) | 
| 文件存在 | fs.stat() / fs.access() | fs.existsSync(path) | 
| 监听文件 | fs.watchFile(filename[, options], listener) | |
| 停止监听 | fs.unwatchFile(filename[, listener]) | |
| 打开大文件 | fs.createReadStream(path[, options]) | |
| 写入大文件 | fs.createWriteStream(path[, options]) | |
| 创建目录 | fs.mkdir(path[, options], callback) | fs.mkdirSync(path[, options]) | 
| 读取目录 | fs.readdir(path[, options], callback) | fs.readdirSync(path[, options]) | 
| 删除目录 | fs.rmdir(path, callback) | fs.rmdirSync(path) | 
form 信息创建文件
form 表单进行一个 post 提交,在浏览器打开 127.0.0.1:9527,此时输入表单信息,填写用户名/密码/备注等信息.点击提交之后会直接在当前目录下创建一个 user.txt 的文件,使用 writeFileSync()同步方法进行创建
writeFileSync()方法
function router(p) {
  ......
    "/": (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      createForm(response);
      response.end();
    },
    "/login": (request, response) => {
      let totalData = "";
      request.on("data", data => {
        totalData += data;
      });
      request.on("end", () => {
        response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
        //username=liudehua&password=123456&remark=%E6%88%91%E6%98%AF%E5%88%98%E5%BE%B7%E5%8D%8E%2C%E6%88%91%E6%98%AF%E4%B8%80%E5%90%8D%E6%AD%8C%E6%89%8B
        //username=liudehua&password=123456&remark=我是刘德华,我是一名歌手
        let decodeData = decodeURIComponent(totalData); //解决中文乱码
        fs.writeFileSync(path.join(__dirname, "/user.txt"), decodeData);
        response.end();
      });
    },
   ......
}
function createForm(response) {
  response.write("<form method='post' action='login'>");
  response.write("<div>用户名:</div><input type='text' name='username'>");
  response.write("</br>");
  response.write("<div>密码:</div><input type='text' name='password'>");
  response.write("</br>");
  response.write(
    "<div>备注:</div><textarea rows='10' cols='30' name='remark'></textarea>"
  );
  response.write("</br>");
  response.write("<input type='submit' value='提交' />");
  response.write("</br>");
}
但是在 node 开发中,同步编程在使用上并没有什么优势,尤其文件读写操作使用异步更好一些
writeFile()的回调函数的形式进行文件写入
let decodeData = decodeURIComponent(totalData); //解决中文乱码
fs.writeFile(path.join(__dirname, "/user.txt"), decodeData, err => {
    if (err) throw err;
    response.end();
});
response.end();
javascript 在 es6 的之后的异步编程的形式发生了一些改变,promise 的引入让异步编程显得更加优雅
//创建file.js
let fs = require("fs");
module.exports = {
  write: function(filename, data, options) {
    return new Promise((resolve, reject) => {
      fs.writeFile(filename, data, options, err =>
        err === null ? resolve(filename) : reject(err)
      );
    });
  }
};
//app.js
let decodeData = decodeURIComponent(totalData); //解决中文乱码
write(path.join(__dirname, "/user.txt"), decodeData)
    .then(res => {
      response.end();
    })
    .catch(err => {
      throw err;
    });
也可以使用 async/await 的方法将 promise 的异步执行转变为同步执行
      request.on("end", async () => {
        response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
        let decodeData = decodeURIComponent(totalData); //解决中文乱码
        await write(path.join(__dirname, "/user.txt"), decodeData);
        response.end();
      });
此时可以使用 try...catch 进行错误捕获了
try {
  await write(path.join(__dirname, "/user.txt"), decodeData);
  response.end();
} catch (err) {
  console.log(err);
  response.end();
}
为什么有同步方法了,还是要先将回调用 promise 包装后再用 async/await 将其转为同步呢?await 会阻塞 async 异步函数,但是并没有阻塞主线程,async 本质上还是异步执行,只是看起来像是一个同步执行,我们可以继续并行执行,而同步方法 sync 则不能并行执行.
追加内容 appendFile 和 appendFileSync
将数据追加(在最后接着写入)到文件,如果文件尚不存在则创建该文件.data 可以是字符串或 Buffer.buffer 内容是十六进制信息的 ASCII 码
和 writeFile 不同是,writeFile 也是将内容写入文件,也是文件不存在就创建,但是文件存在的话,writeFile 写入的内容会直接覆盖原有内容,而 appendFile 是追加内容.所以新建内容还是 writeFile 比较好.
修改 file.js
  append: function(filename, data, options) {
    return new Promise((resolve, reject) => {
      fs.appendFile(filename, data, options, err =>
        err === null ? resolve(filename) : reject(err)
      );
    });
  }
修改 app.js
let { write, append } = require("./file.js");
......
 "/append": async (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      await append(
        path.join(__dirname, "/user.txt"),
        "我要向世界发出hello world"
      );
      response.end();
    },
打开 user.txt 就发现文件的内容是 "username=我是好人&password=123456&remark=今天我要做一件事情我要向世界发出 hello world"
删除文件 fs.unlink 和 fs.unlinkSync
修改 file.js
  remove: function(path) {
    return new Promise((resolve, reject) => {
      fs.unlink(path, err => (err === null ? resolve(path) : reject(err)));
    });
  }
修改 app.js
    "/append": async (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      await remove(path.join(__dirname, "/user.txt"));
      await append(
        path.join(__dirname, "/user.txt"),
        "我要向世界发出hello world"
      );
      response.end();
    },
这样 user.txt 中内容只有"我要向世界发出 hello world"了,可以看出来是删除文件后重新写入的
文件重命名 fs.rename()
还是修改 file.js
  rename: function(oldPath, newPath) {
    return new Promise((resolve, reject) => {
      fs.rename(oldPath, newPath, err =>
        err === null ? resolve([oldPath, newPath]) : reject(err)
      );
    });
  }
然后再 app.js 中执行
 await rename(
        path.join(__dirname, "/user.txt"),
        path.join(__dirname, "/new_name.txt")
      );
文件夹操作 mkdir,rmdir,readdir
mkdir 接受三个参数,第一个是目录名,第二个是权限值,第三个是回调函数
readdir 方法用于读取目录,返回一个所包含的文件和子目录的数组
rmdir 接收一个 path 参数用于删除文件夹
新建 dir.js
let fs = require("fs");
module.exports = {
  mkdir: function(path, options) {
    return new Promise((resolve, reject) => {
      fs.mkdir(path, options, err =>
        err === null ? resolve(path) : reject(err)
      );
    });
  },
  readdir: function(path, options) {
    return new Promise((resolve, reject) => {
      fs.readdir(path, options, (err, files) =>
        err === null ? resolve(files) : reject(err)
      );
    });
  },
  rmdir: function(path) {
    return new Promise((resolve, reject) => {
      fs.rmdir(path, err => (err === null ? resolve(path) : reject(err)));
    });
  }
还是在 app.js 中调用
    "/dir": (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      ["图片", "文件", "书籍", "视频"].forEach(async item => {
        await mkdir(path.join(__dirname, `/${item}`));
        await write(
          path.join(__dirname, `/${item}/${item}.txt`),
          "我还是要向世界发出hello world"
        );
        console.log("我在里面");
      });
      console.log("我在外面");
      response.end();
    },
文件夹此时创建成功了,控制台也会输入"我在外面,我在里面,我在里面,我在里面,我在里面".
在使用同步写一次
"/dir": (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      ["图片", "文件", "书籍", "视频"].forEach(async item => {
        fs.mkdirSync(path.join(__dirname, `/${item}`));
        fs.writeFileSync(
          path.join(__dirname, `/${item}/${item}.txt`),
          "我还是要向世界发出hello world"
        );
        console.log("我在里面");
      });
      console.log("我在外面");
      response.end();
    },
然后控制台输出是"我在里面,我在里面,我在里面,我在里面,我在外面",async/await 的同步终究是个异步,只是在代码块中执行像同步

文件夹操作 readdir
    "/file": async (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      let dir_path = process.cwd();
      let files = await readdir(dir_path);
      let str = `<ul>${files
        .map(item => {
          return `<li><a href="/${item}">${item}</a></li>`;
        })
        .join("")}</ul>`;
      response.write(str);
      response.end();
    },

文件夹操作 rmdir
空文件夹直接删除
    "/clear": async (request, response) => {
      response.writeHead(200, { "Content-type": "text/html;charset=utf-8" });
      ["图片", "文件", "书籍", "视频"].forEach(async item => {
        await rmdir(path.join(__dirname, `/${item}`));
      });
      response.end();
    },
不为空的文件夹是无法直接删除的,删除的是文件而不是文件夹也会报错.
Docs
Node.js fs 文档
fs 模块
nodejs-fs
fs-extra
[Nodejs] node的fs模块的更多相关文章
- 【node】fs模块,文件和目录的操作
		
检查文件是否存在,查询文件信息 fs.stat() fs.stat('./server.js', function (err, stat) { if (stat && stat.isF ...
 - node的fs模块使用————node
		
node的fs模块使用----node fs模块是调用文件的模块. var fs=require('fs'); //引用模块. //查看文件信息 fs.stat('index.txt',functio ...
 - nodejs中的fs模块中的方法
		
nodejs中的fs模块 引入模块 const fs =require("fs") 检测文件是否存在fs.stat(path,callback) fs.stat("./n ...
 - 从官网学习Node.js FS模块方法速查
		
最新文档请查看仓库 https://github.com/wangduandu... 1. File System 所有文件操作提供同步和异步的两种方式,本笔记只记录异步的API 异步方式其最后一个参 ...
 - Node.js FS模块方法速查
		
1. File System 所有文件操作提供同步和异步的两种方式,本笔记只记录异步的API 异步方式其最后一个参数是回调函数.回调函数的第一个参数往往是错误对象,如果没有发生参数,那么第一个参数可能 ...
 - Node.js——fs模块(文件系统),创建、删除目录(文件),读取写入文件流
		
/* 1. fs.stat 检测是文件还是目录(目录 文件是否存在) 2. fs.mkdir 创建目录 (创建之前先判断是否存在) 3. fs.writeFile 写入文件(文件不存在就创建,但不能创 ...
 - node的fs模块
		
node的file system模块提供的api有同步和异步两种模式(大多数情况下都是用的异步方法,毕竟异步是node的特色,至于提供同步方法,可能应用程序复杂的时候有些场景使用同步会比较合适).异步 ...
 - node之fs模块
		
前言 fs是filesystem的缩写,该模块提供本地文件的读写能力,基本上是POSIX文件操作命令的简单包装.但是,这个模块几乎对所有操作提供异步和同步两种操作方式,供开发者选择. 一.文件读取 文 ...
 - node中fs模块 - fs.open()  fs.read()  fs.write()  fs.close()
		
var fs = require('fs') fs.open('./a.txt', 'a+', function(err, fd) { // 打开文件后 创建缓冲区放置数据 ), // 读取多少字节 ...
 
随机推荐
- ELK---日志分析系统
			
ELK就是一套完整的日志分析系统 ELK=Logstash+Elasticsearch+Kibana 统一官网https://www.elastic.co/products ELK模块说明 Logst ...
 - java jackson 忽略不存在的属性字段 和 按照属性名转json
			
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, isGetterVisibi ...
 - python环境下实现OrangePi Zero寄存器访问及GPIO控制
			
最近入手OrangePi Zero一块,程序上需要使用板子上自带的LED灯,在网上一查,不得不说OPi的支持跟树莓派无法相比.自己摸索了一下,实现简单的GPIO控制方法,作者的Zero安装的是Armb ...
 - 【转】百度站长平台MIP引入工具使用心得
			
MIP引入主动推送流程 对于 MIP 站点改造好了,我们如何提交数据,并且 MIP 提交后,我们能得到哪些数据的反馈,在这里简单的写一篇文章,说一下. 改造 MIP,我们一般是添加了一个二级域名站点进 ...
 - 阿里云大数据计算服务 - MaxCompute (原名 ODPS)
			
MaxCompute 是阿里EB级计算平台,经过十年磨砺,它成为阿里巴巴集团数据中台的计算核心和阿里云大数据的基础服务.去年MaxCompute 做了哪些工作,这些工作背后的原因是什么?大数据市场进入 ...
 - 【坑】解决CentOS 7.1版本以上安装好zabbix 3.4 无法重启zabbix-server的问题
			
1. 问题所在 报错信息:zabbix_server[]: segfault at ip 00007f78842b4bd0 sp 00007fff1995a818 error ] 2. 产生原因 Ce ...
 - csdn阅读更多需要注册登录csdn
			
csdn目前设置每日使用5次后必须登录才能看到阅读更多的内容,异常恶心.因此搜罗了方法去解决这个问题 方法一 打开想看的csdn后,在console里边执行以下代码: $("div.arti ...
 - Netty源码—四、事件处理
			
前面经过channel初始化.注册,所需要的数据结构(epoll_event)基本上准备好了,serverSocket也处于监听状态,可以接收来自客户端的请求了.NioServerSocketChan ...
 - Docker进阶之六:网络管理
			
一.默认网络 安装Docker时会自动创建三个网络:docker network ls 列出网络: # docker network ls NETWORK ID NAME DRIVER SCOPE 5 ...
 - Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget
			
前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...