fs--文件系统

本文介绍了Node.js中的文件系统操作,重点讨论了fs模块的使用,包括同步和异步读写文件、目录操作、文件信息获取、删除、流处理等。详细阐述了如何进行小文件及大文件的拷贝,并强调了流在处理大文件时的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件系统概述

任何一门编程语言,尤其是后端的语言,都提供了文件系统的相关操作。

让前端觉得如获神器的不是NodeJS能做网络编程,而是NodeJS能够操作文件。小至文件查找,大至代码编译,几乎没有一个前端工具不操作文件。换个角度讲,几乎也只需要一些数据处理逻辑,再加上一些文件操作,就能够编写出大多数前端工具

文件,可以是任何的文件,包括文档、图片、电影、音频等文件。

  • 百度云盘 文件的上传和下载
  • 在开发的过程中,经常使用的一些构建工具,也是对文件进行相关的操作。比如npm、 webpack、vue-cli、gulp,都是对文件的相关操作。

所以说,文件操作是编程领域中非常重要的一个方面。浏览器端的js是不允许操作文件,基于安全考虑。但是服务端必须要提供对文件操作的支持,因为服务端是安全的。

在node.js中,文件系统的操作是使用fs核心模块来实现的。

针对这个fs,重点是如下两个方面:

  • 常见的文件操作:读取、写入、删除、判断存在性、文件信息
  • 常见的目录操作:创建、删除、读取

在fs模块中,基本上所有的操作都有两个版本:

  • 同步版本
  • 异步版本

读取文件

readFile / readFileSync

fs.readFile('./index.js','utf8',function(err,data){
    if(err){
        throw err
    }
    console.log(data);
})     
fs.readFileSync('./index.js','utf8');

注意:

  • 在读取文件的时候,默认使用的buffer,需要设置相应的字符集编码,对于文本文件,就设置为utf8.
  • 在node的文件操作中,异步的回调函数是错误优先的回调,错误信息对象作为回调函数的第一个参数

同步和异步的区别

获取结果的方式不同,异步是通过回调的参数获取的,而同步是通过方法返回值获取的
执行顺序不同

覆盖式写文件

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

eg:小文件拷贝
	1、异步
	fs.readFile('./a.js', function (err, data) {
		if (err) {
			throw err;
		}
		fs.writeFile('./b.js', data, function (err) {
			if (err) {
				throw err;
			}
		});
	});
    2、同步
	fs.writeFileSync('./b.js', fs.readFileSync('./a.js'));

追加式写文件

fs.appendFile(file,data,[options],callback) / fs.appendFileSyncfs.writeFileSync(file,data,[options])

删除文件

fs.unlink(path,callback) / fs.unlinkSync(path)

判断文件是否存在

fs.exists(废弃) / fs.existsSync(path)

获取文件信息

fs.stat(path,callback) / fs.statSync(path)

callback 中文件信息对象 stats类

文件类型有很多种,在linux中,有7种。而在windows下面只有两种:

文件 stats.isFile()
目录 stats.isDirectory()

eg: 拷贝lib下的所以文件以及文件夹
	fs.readdir('./lib', function (err, paths) {
		if (err) {
			throw err;
		}
		paths.forEach(function (file) {
			fs.stat('./lib/' + file, function (err, st) {
				if (err) {
					throw err;
				}
				if (st.isFile()) {
					fs.writeFileSync('./dist/' + file, fs.readFileSync('./lib/' + file));
				} else {
					if (!fs.existsSync('./dist/' + file)) {
						fs.mkdirSync('./dist/' + file);
					}
				}
			});
		});
	});

创建目录

fs.mkdir(path,callback) / fs.mkdirSync(path)

在使用mkdir创建目录的时候,只能创建单层目录,不能递归的创建目录。
path在书写路径格式时必须确认父路径存在才能创建子路径

删除目录

fs.rmdir(path,callback) / fs.rmdirSync(path)

rmdir只能删除空目录,如果目录是非空的,则无法删除
如果需要删除某个目录,首先就应该先删除目录中的内容,最后再删除目录本身

读取目录

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

eg:拷贝文件夹下的所以文件
	fs.readdir('./lib', function (err, paths) {
		paths.forEach(function (file) {
			fs.readFile('./lib/' + file, function (err, data) {
				if (err) {
					throw err;
				}
				fs.writeFileSync('./dist/' + file, data);
			});
		});
	});

递归删除目录

由于rmdir方法,只能删除空目录,如果一个目录下有很多内容,尤其是嵌套了很多层的文件夹,只能一层一层的来删,应该使用递归的思想来实现。

只要有递归,就需要定义函数。

可以封装一个函数,用于删除指定目录。

如果没有递归,通常用异步的文件操作。有了递归,需要使用同步的文件操作。

node流

流是Node.js中一个非常重要的概念, 也是Node.js之所以适用于I / O密集型场景的重要原因之一。 流是Node.js移动数据的方式, 流可以是可读的和/ 或可写的。 在Node.js中很多模块都使用到了流, 包括HTTP和fs模块

由于数据是流, 这就意味着在完成文件读取之前, 从收到最初几个字节开始, 就可以对数据动作。

由于一次性读取再写入的方式不适用与大文件拷贝, 容易造成内存爆仓, 对于大文件, 我们只能读一点儿写一点儿直到拷贝完成

创建一个只读数据流
var rs = fs.createReadStream('./src/1.mp4');
创建一个只写数据流
var ws = fs.createWriteStream('./src/2.mp4');
管道流输出
rs.pipe(ws); 

大文件拷贝实现原理

// 创建一个只读数据流
var readStream = fs.ReadStream('./src/1.mp4'); 
// 创建一个只写数据流
var writeStream = fs.WriteStream('./src/2.mp4');
// 在内存中监听到只读数据流时触发
rs.on('data', function (chunk) {
	// ws.write(chunk); 将读取到的文件写入目标容器,返回布尔值 没写完-> false 写完-> true
	if (!ws.write(chunk)) {  // 如果没写完
		rs.pause();// 暂停只读数据流
		console.log('pause');
	}
});
// drain事件来判断什么时候只写数据流已经将缓存中的数据写入目标,可以传入下一个待写数据
ws.on('drain', function () {
	rs.resume(); // 循环读取
	console.log('resume');
});
// 读完
rs.on('end', function () {
	ws.end();
	console.log('end');
});
eg:将src下的小文件拷贝到small目录中,大文件以流的形式拷贝到big目录中
fs.readdir('./src', function (err, paths) {
	if (err) {
		throw err;
	}
	paths.forEach(function (file) {
		fs.stat('./src/' + file, function (err, st) {
			if (err) {
				throw err;
			}
			if (st.size / 1024 / 1024 > 300) {
				createDir('./big', function () {
					var rs = fs.createReadStream('./src/' + file);
					var ws = fs.createWriteStream('./big/' + file);
					rs.pipe(ws);
				});
			} else {
				createDir('./small', function () {
					fs.writeFileSync('./small/' + file, fs.readFileSync('./src/' + file));
				});
			}
		});
	});
});
function createDir (dist, ck) {
	if (!fs.existsSync(dist)) {
		fs.mkdirSync(dist);
	}
	ck && ck();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值