node.js学习笔记(二)文件系统
本文由 小茗同学 发表于 2016-11-02 浏览(2973)
最后修改 2020-12-22 标签:nodejs fs 文件系统 node.js

前言

文件系统对于写一些小脚本、小工具而言非常重要,所以最先介绍文件系统相关方法的使用。

中文文档:http://nodejs.cn/api/fs.html

常见API

const fs = require('fs');
const path = 'test.txt';
const content = '这是新写入的文件内容';

// 写入文件,编码默认就是utf8
fs.writeFileSync(path, content, 'utf-8');

// 读取文件,如果指定编码就返回字符串,否则返回buffer
console.log(fs.readFileSync(path, 'utf-8'));

// 判断是文件还是目录
var stat = fs.statSync(path);
console.log('是否是目录:' + stat.isDirectory());
console.log('是否是文件:' + stat.isFile());

// 判断是否存在
fs.existsSync(path);

// 删除文件
fs.unlinkSync(fileName);

// 新建文件夹
fs.mkdirSync(folderName);

// 删除文件夹,注意这个只能删除空文件夹,非空会报错
fs.rmdirSync(folderPath);

// 重命名
fs.renameSync(oldPath, newPath);

// 遍历文件夹,files是新文件名组成的数组,非完整路径,包括 . 和 .. 
var files = fs.readdirSync(path);

新建多层文件夹

默认的fs.mkdirSync(path)无法创建多层文件夹,需要自己实现:

/**
 * 同步创建多层文件夹
 * @param 文件夹路径,必须时“/”分隔,如:res/css/bootstrap
 * @param 模式,可选
 */
function mkdirsSync(dirpath, mode)
{
	if (fs.existsSync(dirpath)) return true;
	var temp = '', sep = '/';
	dirpath.split(sep).forEach(function(dirname)
	{
		temp += (temp ? sep : '') + dirname;
		console.log(temp);
		if (fs.existsSync(temp)) return;
		if (!fs.mkdirSync(temp, mode)) return false;
	});
	return true;
}

递归遍历文件夹

简单写了2个示例方法,一个是异步的,一个是同步的,异步的不太好判断何时遍历结束,可以配合Promise使用,但是个人觉得遍历一个文件夹有啥好异步的,又不涉及网络,所以推荐使用同步方法

异步遍历:

function scanFolder(path, callback, idx)
{
	idx = idx == undefined ? 0 : idx;
	fs.stat(path, function(error, stat)
	{
		if(error) throw new Error(error);
		// 如果是文件,无需遍历
		if(!stat.isDirectory()) callback(path, idx);
		else
		{
			fs.readdir(path, function(err, files)
			{
				if(err) throw new Error(err);
				else
				{
					files.forEach(function(file)
					{
						scanFolder(path + '/' + file, callback, idx+1);
					});
				}
			});
		}
	});
}

同步遍历:

/**
 * 遍历某个文件夹
 */
function scanFolderSync(folderPath, callback) {
	let idx = arguments[2] == undefined ? 1 : idx;
	if(!fs.statSync(folderPath).isDirectory()) callback(folderPath, idx);
	else {
		fs.readdirSync(folderPath).forEach(function(file) {
			var tempPath = folderPath + '/' + file;  
			if(fs.statSync(tempPath).isDirectory()) scanFolderSync(tempPath, callback, idx+1);
			else callback(tempPath, idx);
		});
	}
},

第三方库: fs-extra

原生fs功能有限,强烈推荐使用第三方库 fs-extra ,它100%向下兼容,包含了fs全部功能并新增了一些实用方法

npm install --save fs-extra

使用(可以用fs-extra完全替代fs):

const fs = require('fs-extra');

使用示例(以下全是异步方法,同步方法全部加一个Sync结尾):

const fs = require('fs-extra');
async function example () {
	// 复制一个文件或者一个目录,默认覆盖
	await fs.copy('xxx/oldFileOrDir', 'xxx/newFileOrDir'', {overwrite: false});
	// 清空一个目录,如果这个目录不存在,创建一个新的,可以理解为 emptyDirSync = removeSync + mkdirsSync
	fs. emptyDirSync('xxx');
	// 如果某个目录不存在,创建它,支持多级目录的创建,mkdirs、mkdirp、ensureDir 3个功能一模一样,只是不同的别名
	fs.mkdirsSync('xxx');
	// 移动一个文件或者一个目录,默认不覆盖
	await fs.move('xxx/oldFileOrDir', 'xxx/newFileOrDir'', {overwrite: true});
	// 几乎完全等价于原生 fs.writeFile,唯一区别是如果父目录不存在则创建之,注意原生 fs.writeFile 默认就是override为true
	await fs.outputFile('xxx/xxx.txt', '内容');
}
example()