nodejs---fs模块,文件读写操作详解,自定义一个文件写入方法

fs模块导入

Node.js 同时支持 CommonJS 和 ES 模块系统(自 Node.js v12 以来)

// 两种模块导入方式
import * as fs from 'fs';// Es6:这种方式需要在package.json中配置"type": "module"
const fs = require('fs');// commonJs:如果你只有一个单文件js那么你还是要使用这种方式导入

是否使用ES6的导入方式,取决于你是否有一个配置文件,或者就使用require导入

fs的读写文件方法

fs提供的文件操作方法包含3中模式:回调式,阻塞式,promise式

这里使用stat()方法举例,

检查文件信息 stat()

const fs = require('fs');// commonJs
const txt = '../public/file.txt'// 回调式
fs.stat(txt, (err, stats) => {if(err){console.log(err.message);}console.log(stats.isFile());
})// 阻塞式
try {const stats = fs.statSync(txt);
} catch (err) {console.error(err);
}
console.log(stats.isFile());// promise式
async function example() {try {const stats = await fs.stat(txt);} catch (err) {console.log(err);}console.log(stats.isFile());
}
example();

使用后面两种方法时需要使用try,catch来捕获错误,

这里要注意 :如果不存在txt路径的文件,会产生错误,这种错误式 被捕获的err提示的,并非式致命错误(直接终止程序),它会提示你没有这个文件,而后面对这个文件的操作也会无法执行,

读取文件内容 readFile()

// 读取文件, 读取文件内容,并返回一个字符串
fs.readFile(txt, 'utf8', (err, data) => {if(err){console.log(err.message);}console.log(data);
}) 

参数:文件路径,读取格式(默认式二进制流格式),回调参数,err错误信息,data读取的数据

同样的,readFile也支持三种模式:回调式,阻塞式,promise式,这里仅展示回调式

写入文件writeFile()

// 写入文件, 写入文件内容,
fs.writeFile(txt, 'hello world', (err) => {if(err){console.log(err.message);}console.log('写入成功');
})

参数:文件路径,写入的内容,回调参数,err错误信息

同样的,writeFile也支持三种模式:回调式,阻塞式,promise式,这里仅展示回调式

追加内容appendFile()

fs.appendFile(txt, 'hello world', (err) => {if(err){console.log(err.message);}console.log('追加成功');
})

参数:文件路径,写入的内容,回调参数,err错误信息

同样的,appendFile也支持三种模式:回调式,阻塞式,promise式,这里仅展示回调式

注意 writeFile会覆盖原内容,从起始位置开始写入,appendFile不覆盖原内容,从末尾位置开始写入

文件夹操作

判断一个文件夹是否存在
使用 fs.existsSync(),这里exists不推荐使用了,事实上,对于文件夹的操作都建议使用阻塞式,因为文件都必须在文件夹下操作,文件夹没有被获取的话,文件操作就无法正常执行
新建一个文件夹
使用 fs.mkdir() 或 fs.mkdirSync()  创建新文件夹
读取目录的内容
使用 fs.readdir() 或 fs.readdirSync() 读取目录的内容。
重命名文件夹
使用 fs.rename() 或 fs.renameSync()  重命名文件夹。
删除文件夹
使用 fs.rmdir() 或 fs.rmdirSync() 删除文件夹。

新建一个文件夹

这里展示如何新建一个文件夹,其他方法类似,想了解更多可以参考:在 Node.js 中使用文件夹 (nodejs.cn)

const fs = require('fs');
const path = "./public/";try {// 如果没有public文件夹则创建if (!fs.existsSync(path)) {fs.mkdirSync(path);}
} catch (err) {console.error(err);
}

封装一个setFile方法

了解了基本的读写操作后我们可以封装一个方法,

该函数接收一个文件名和一个文件内容作为参数,并将文件内容写入指定的文件中(没有则创建),路径是当前目录下新建一个public文件夹,并将文件至于public下面。

/*** @param {文件名称} baseName * @param {写入的内容} content * @param {内容是否覆盖} b 默认为false,不覆盖*/setFile(baseName,content,b)
module.exports.setFile = function (baseName, content, b = false) {// 如果没有public文件夹则创建try {if (!fs.existsSync(path)) {fs.mkdirSync(path);console.log("文件夹 public 创建成功");}} catch (err) {console.log(err);}// 判断文件是否存在,在open之前判断,回调结果在open之后fs.stat(path + baseName, (err) => {if (err) {// 文件不存在,产生错误// console.log(err);console.log(`文件 ${baseName} 创建成功`);}})if (!b) {// 不覆盖内容// fs.readFile(path + baseName, "utf-8",(err, data) => {//   if (err) {//     console.error(err);//   }//   // 读取出原来的内容拼接//   content = data + content;//   fs.writeFile(path + baseName, content, (err) => {//     if (err) {//       console.error(err);//     }//     console.log("写入成功");//   })// })fs.appendFile(path + baseName, content, (err) => {if (err) {console.error(err);} else {console.log("写入成功");}})} else {fs.writeFile(path + baseName, content, (err) => {if (err) {console.error(err);} else {console.log("写入成功");}})}}

在同目录下新建一个useSetFile.js导入这个方法

// 导出的模块是整个文件,需要通过属性引入使用里面的方法
const setFile = require('./setFile');const file = 'file.txt';
const content = 'Hello, World!';setFile.setFile(file, content);

在控制台执行node useSetFile.js

 

可以看到目录下多了一个public文件夹和file.txt文件,并且写入了两个hello,world!

数据流缓冲区读写---open,close,read,write方法

出来file后缀的文件操作方法,fs模块还有基于数据流的读写方法,关于二进制数据流可以参考:

js二进制数据,文件---ArrayBuffer,二进制数组_js arraybuffer()-CSDN博客

// 打开文件,'w+/a+' 获得读,写权限,文件流起始位置在开头/末尾(a相比于a+没有读取权限), 如果文件不存在则创建,读取文件后会覆盖原有文件
fs.open(txt, 'a', (err, fd) => {if(err){console.log(err.message);}// 关闭文件, 关闭文件后才能进行其他操作fs.close(fd, (err) => {if(err){console.log(err.message);}console.log('文件关闭成功');})
})
/*** fd, 使用fs.open打开成功后返回的文件描述符* buffer, 一个Buffer对象,v8引擎分配的一段内存* offset, 整数,从缓存区中读取/写入时的初始位置,以字节为单位* length, 整数,从缓存区中读取/写入数据的字节数* position, 整数,写入/读取文件初始位置;* callback(err, written, buffer), 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象*/
fs.write(fd, buffer, offset, length, position, callback);
fs.read(fd, buffer, offset, length, position, callback);

整体的使用结构为

open->read/write->close

open开始拿到fd,fd为一个整数,表示打开文件返回的文件描述符,window中又称文件句柄

后续操作以fd为文件标志进行操作

const fs = require('fs');
const path = __dirname+"/public/buffer.txt";// __dirname 当前文件所在目录的绝对路径
const buffer = new Buffer.from("你好");  //每一个汉字utf8编码是3个字节,英文是1个字节fs.open(path, 'a+', (err, fd) => {fs.write(fd,buffer,0,6,0, (err) => {// 0,6,0的含义,0,6从buffer中读取6个字节,0是开始读取的位置,0是写入的位置,写入文件的起始位置  if(err){console.log(err);}else{console.log("写入成功");}})fs.read(fd,buffer,0,6,0, (err, bytes) => {// 0,6,0的含义,0,6从buffer中写入6个字节,0是开始写入的位置,0是读取的位置,读取文件的起始位置if(err){console.log(err);}else{if(bytes > 0){console.log(buffer.slice(0, bytes).toString());//打印buffer中的内容fs.read(fd,buffer,0,6,null, (err, bytes) => {// 再次读取fd中的内容时,不标记出读取位置,默认为上次读取结束的位置,'a+'表示每次将位置放置在文件末尾if(err){console.log(err);}else{if(bytes > 0){console.log(buffer.slice(0, bytes).toString());}}})}fs.close(fd, (err) => {//结束本次文件读写if(err){console.log(err);}else{console.log("关闭文件成功");}})}})});

这种方式的逻辑更加精细,可以控制数据流缓存区的位置进行读写,

值得注意的是,read和write两个方法中的3个整数参数,前两个是指定给buffer数据流缓冲区的 ,最后一个是文件的位置,当你进行read读取时,是对文件进行读取,在将读取的内容写入buffer

当你进行write写入时,是对buffer进行读取,在将读取的内容写入文件 ,两者正好相反但是参数格式一致

完整代码总结和目录结构展示

file.js

// 两种模块导入方式
// import * as fs from 'fs';// Es6:这种方式需要在package.json中配置"type": "module"
const fs = require('fs');// commonJs
const path = require('path');const txt = '../public/file.txt'
const txtMsg = [path.dirname(txt),// 父级文件夹path.basename(txt),// 文件名,包括后缀path.extname(txt) // 文件后缀(扩展名)
]let f = 0 ;txtMsg.forEach(item => {console.log(item);
})// 同一代码块的回调执行顺序是 fs.open -> fs.close ->fs.stat -> fs.writeFile -> fs.readFile 打开文件,关闭文件,查看文件,写入文件,读取文件
// 打开文件,'w+/a+' 获得读,写权限,文件流起始位置在开头/末尾(a相比于a+没有读取权限), 如果文件不存在则创建,读取文件后会覆盖原有文件
fs.open(txt, 'a', (err, fd) => {if(err){console.log(err.message);}f = fd;console.log(fd); 
})// 读取文件, 读取文件内容,并返回一个字符串
fs.readFile(txt, 'utf8', (err, data) => {if(err){console.log(err.message);}console.log(data);
}) // 写入文件, 写入文件内容,
fs.writeFile(txt, 'hello world', (err) => {if(err){console.log(err.message);}console.log('写入成功');
})// 追加文件内容
fs.appendFile(txt, 'hello world', (err) => {if(err){console.log(err.message);}console.log('追加成功');
})// 关闭文件, 关闭文件后才能进行其他操作
fs.close(f, (err) => {if(err){console.log(err.message);}console.log('文件关闭成功');
})// 文件信息
fs.stat(txt, (err, stats) => {if(err){console.log(err.message);}console.log(stats.isFile());
})// 每次执行此文件,会先打开txt.txt文件,(此时内容已清空)关闭文件,写入内容,再读取文件内容

setFile.js

// 封装一个setFile函数,该函数接收一个文件名和一个文件内容作为参数,并将文件内容写入指定的文件中(没有则创建),路径是当前目录下新建一个public文件夹,并将文件至于public下面。
// setFile(baseName,content,b)const fs = require('fs');
const path = "./public/";/*** @param {文件名称} baseName * @param {写入的内容} content * @param {内容是否覆盖} b 默认为false,不覆盖*/module.exports.setFile = function (baseName, content, b = false) {// 如果没有public文件夹则创建try {if (!fs.existsSync(path)) {fs.mkdirSync(path);console.log("文件夹 public 创建成功");}} catch (err) {console.log(err);}// 判断文件是否存在,在open之前判断,回调结果在open之后fs.stat(path + baseName, (err) => {if (err) {// 文件不存在,产生错误// console.log(err);console.log(`文件 ${baseName} 创建成功`);}})if (!b) {// 不覆盖内容// fs.readFile(path + baseName, "utf-8",(err, data) => {//   if (err) {//     console.error(err);//   }//   // 读取出原来的内容拼接//   content = data + content;//   fs.writeFile(path + baseName, content, (err) => {//     if (err) {//       console.error(err);//     }//     console.log("写入成功");//   })// })fs.appendFile(path + baseName, content, (err) => {if (err) {console.error(err);} else {console.log("写入成功");}})} else {fs.writeFile(path + baseName, content, (err) => {if (err) {console.error(err);} else {console.log("写入成功");}})}
}

useSetFile.js

// 导出的模块是整个文件,需要通过属性引入使用里面的方法
const setFile = require('./setFile');const file = 'file.txt';
const content = 'Hello, World!';setFile.setFile(file, content);

buffer.js

const fs = require('fs');
const path = __dirname+"/public/buffer.txt";// __dirname 当前文件所在目录的绝对路径
const buffer = new Buffer.from("你好");  //每一个汉字utf8编码是3个字节,英文是1个字节fs.open(path, 'a+', (err, fd) => {fs.write(fd,buffer,0,6,0, (err) => {// 0,6,0的含义,0,6从buffer中读取6个字节,0是开始读取的位置,0是写入的位置,写入文件的起始位置  if(err){console.log(err);}else{console.log("写入成功");}})fs.read(fd,buffer,0,6,0, (err, bytes) => {// 0,6,0的含义,0,6从buffer中写入6个字节,0是开始写入的位置,0是读取的位置,读取文件的起始位置if(err){console.log(err);}else{if(bytes > 0){console.log(buffer.slice(0, bytes).toString());//打印buffer中的内容fs.read(fd,buffer,0,6,null, (err, bytes) => {// 再次读取fd中的内容时,不标记出读取位置,默认为上次读取结束的位置,'a+'表示每次将位置放置在文件末尾if(err){console.log(err);}else{if(bytes > 0){console.log(buffer.slice(0, bytes).toString());}}})}fs.close(fd, (err) => {//结束本次文件读写if(err){console.log(err);}else{console.log("关闭文件成功");}})}})});

目录结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/24626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golang协程工作池处理多任务示例

1. 工作方法实现 // 工作线程 // id : 线程号 // jobs : 任务通道 (chan) // results: 完成结果通道 (chan) func worker(id int, jobs <-chan int, results chan<- int) {//遍历任务for j : range jobs {fmt.Println("工作协程: ", id, "启动任务: &quo…

vscode输出控制台中文显示乱码最有效解决办法

当VSCode的输出控制台中文显示乱码时&#xff0c;一个有效的解决办法是通过设置环境变量来确保编码的正确性。以下是解决方式&#xff1a; 首先&#xff0c;设置环境变量以修正乱码问题&#xff1a; 如果上述方法没有解决乱码问题&#xff0c;请继续以下步骤&#xff1a; 右键…

技术革命的十年:计算机、互联网、大数据、云计算与AI

近10年来&#xff0c;计算机、互联网、大数据、云计算和人工智能等技术领域发展迅速&#xff0c;带来了巨大的变革和创新。以下是各个领域的发展历史、现状、问题瓶颈、未来趋势以及可能的奇点。 计算机技术&#xff1a; 发展历史&#xff1a; 过去&#xff1a;过去十年间&am…

RocketMQ的安装

首先到RocketMQ官网下载页面下载 | RocketMQ (apache.org)&#xff0c;本机解压缩&#xff0c;作者在这里用的是最新的5.2.0版本。按照如下步骤安装。 1、环境变量配置rocket mq地址 ROCKETMQ_HOME D:\rocketmq-all-5.2.0-bin-release 在变量path中添加”%ROCKETMQ_HOME%\bi…

免费数据库同步软件

在信息化日益发展的今天&#xff0c;数据同步成为了企业和个人用户不可或缺的一部分。数据库同步软件作为数据同步的重要工具&#xff0c;能够帮助我们实现不同数据库系统之间的数据复制和同步&#xff0c;确保数据的一致性和完整性。本文将介绍几款免费数据库同步软件&#xf…

elasticsearch安装与使用(1)-使用docker安装Elasticsearch

ES的优点&#xff1a; 1、分布式准实时2、提供REST风格的API接口&#xff0c;是用户可解借助任何语言使用https对ES执行请求来完成搜索任务&#xff1b;3、提供聚合功能 1、Elasticsearch安装 docker network create elastic docker pull docker.elastic.co/elasticsearch/e…

【MYSQL系列】mysql中text,longtext,mediumtext区别

【MYSQL系列】mysql中text,longtext,mediumtext区别 在MySQL数据库中&#xff0c;TEXT、LONGTEXT和MEDIUMTEXT都是用于存储大量文本数据的字段类型。它们之间的主要区别在于可存储的数据大小和性能方面的差异。本文将探讨这些字段类型的特点、使用场景和一些最佳实践。 TEXT类…

贪心(不相交的开区间、区间选点、带前导的拼接最小数问题)

目录 1.简单贪心 2.区间贪心 不相交的开区间 1.如何删除&#xff1f; 2.如何比较大小 区间选点问题 3.拼接最小数 1.简单贪心 比如&#xff1a;给你一堆数&#xff0c;你来构成最大的几位数 2.区间贪心 不相交的开区间 思路&#xff1a; 首先&#xff0c;如果有两个…

调试环境搭建(Redis 6.X 版本)

今儿&#xff0c;我们来搭建一个 Redis 调试环境&#xff0c;目标是&#xff1a; 启动 Redis Server &#xff0c;成功断点调试 Server 的启动过程。使用 redis-cli 启动一个 Client 连接上 Server&#xff0c;并使用 get key 指令&#xff0c;发起一次 key 的读取。 视频可见…

【python解决】查询报%d format: a number is required, not str问题

【Python解决】查询报%d format: a number is required, not str问题 在Python中&#xff0c;字符串格式化是一种常见的操作&#xff0c;用于创建包含变量的字符串。如果你在使用%操作符进行格式化时遇到了%d format: a number is required, not str的错误&#xff0c;这意味着…

基于SSM的旅游民宿预定系统【源码】【运行教程】

基于SSM的旅游民宿预定系统 一、项目介绍1. 游客功能2. 管理员功能3. 高级功能 二、项目技术栈三、项目运行四、项目演示总结 大家好&#xff0c;这里是程序猿代码之路&#xff01;随着旅游业的快速发展&#xff0c;民宿作为一种独特的住宿方式越来越受到游客的喜爱。为了提升用…

百华鞋业祝莘莘学子旗开得胜,一举夺魁

在知识的海洋中&#xff0c; 有一群人以笔为剑&#xff0c; 在漫长的岁月里不断磨砺&#xff0c; 只为迎接那场人生的重要战役——高考。 高考&#xff0c; 是学子们十几年寒窗苦读的见证&#xff0c; 是他们用奋斗书写青春考卷的舞台。 在这个舞台上&#xff0c; 他们将…

当前主流的App开发技术综述

一、引言 随着移动互联网的蓬勃发展&#xff0c;App&#xff08;应用程序&#xff09;已经成为人们日常生活中不可或缺的一部分。无论是社交、购物、娱乐还是工作学习&#xff0c;App都以其便捷、高效和个性化的特点深受用户喜爱。而在这一过程中&#xff0c;App开发技术也在不…

ChatGPT-4o体验demo

OpenAI 最近推出了其最新的人工智能语言模型——GPT-4O。该模型是在原有 GPT-4 的基础上进行优化而成&#xff0c;旨在提升生成质量和响应速度。GPT-4O 采用了更加高效的架构设计&#xff0c;使其在处理复杂文本时表现出更快的速度和更高的准确性。GPT-4O 在训练过程中融入了最…

kafka的leader和follower

leader和follower kafka的leader和follower是相对于分区有意义的&#xff0c;不是相对于broker。 因为每个分区都有leader和follower, leader负责读写数据。 follower负责复制leader的数据保存到自己的日志数据中&#xff0c;并在leader挂掉后重新选举出leader。 kafka会再…

(2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干

Vision-LSTM: xLSTM as Generic Vision Backbone 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 2 方法 3 实验 3.1 分类设计 4 结论 0. 摘要 Transformer 被广泛用作计算…

反射型xss靶场练习

反射型xss危害小&#xff0c;这里使用的xss靶场是常用的xss靶场&#xff1a;xss-labs。 当我们完成弹窗后就通过该关卡&#xff0c;说该关卡存在xss的一个漏洞并且可以解析js代码。 第一关&#xff1a; 这里没有过滤我们输入的代码&#xff1a;直接将js代码放在js代码中&a…

Linux下线程的互斥与同步详解

&#x1f916;个人主页&#xff1a;晚风相伴-CSDN博客 &#x1f496;如果觉得内容对你有帮助的话&#xff0c;还请给博主一键三连&#xff08;点赞&#x1f49c;、收藏&#x1f9e1;、关注&#x1f49a;&#xff09;吧 &#x1f64f;如果内容有误或者有写的不好的地方的话&…

centos7 安装 mysql5.7 LTS

centos7 安装 mysql5.7 LTS 参考&#xff1a; https://blog.csdn.net/EB_NUM/article/details/105425622 可以在运行安装程序之前导入密钥&#xff1a; sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022第一步、下载MySQL 安装包&#xff1a; sudo wget h…

植物大战僵尸杂交版破解C++实现

文章目录 前言准备工作&#xff1a;基地址与偏移UI界面设计和绑定项目模板总览图生成与实现信号处理1、阳光值更新:BTN12、三种钱币值更新:BTN2-BTN43、冷却刷新:BTN54、锁定阳光&#xff1a;check15、无冷却&#xff1a;check26、OnTimer&#xff08;&#xff09;和OnClose&am…