内容大纲
fs模块
fs文件系统模块,这是一个非常重要的模块,对文件的操作都基于它,该模块的所有方法都有同步和异步两种方式。对于异步的回调方法,第一次参数都是error对象,error first
const fs=require('fs')
属性
文件(夹)是否存在
fs.access(filepath,exist=>{})
fs.access(filepath,error=>{
...
})
统计信息
fs.stat(path,(error,stats)=>{})
- stats.isFile() : 是否是文件
- stats.isDirectory(): 是否是文件夹
- stats.mod: 获取权限
- stats.size: 字节长度
- stats.ctime:State Change Time,属性或内容上次被修改的时间 (设置缓存的响应头可能会用到)
- stats.mtime:Modified time,档案的内容上次被修改的时间 (设置缓存的响应头可能会用到)
- stats.atime:Access time,上次被读取的时间
文件
创建
fs没有直接创建文件的方法。正常逻辑下,写入文件前需要确认文件是否存在,如果不存在需要创建后才能写入,而fs模块不需要这么做,在有写入功能的几个api中,如果目标文件不存在,node为自动创建该文件然后写入。常用的几个写入功能的api有:
- fs.appendFile()
- fs.writeFile()
- fs.createWriteStream()
删除
上图中的第二部分是文件或者目录的连接(link)数(ln(即link) 的功能是为某一个文件在另外一个位置建立一个同步的链接。有两种链接方式,一种是硬链接(hard link),另一种是符号链接(symbolic link),又称软链接。硬链接和原有文件是存储在同一物理地址的两个不同的名字,因此硬链接是相互的;符号链接的内容只是一个所链接文件的文件名,在使用ls –l时,符号链接的第一项的第一位为“l”。)。目标文件可能是文件实体也可能是一个link,删除时只需要删除link即可,当最后一个link被移除时,实体文件也被删除了。
fs.unlink()
fs.unlink(filepath,error=>{
...
})
复制
fs.copyFile(src, dest[, flags], callback)
重命名
fs.rename(oldPath, newPath, callback)
可实现文件的重命名和移动
文件内容
打开
fs.open(filename,flags,[mode],callback);
fs.open('./1,txt','r',0600,function(err,fd){});
读取
- 读取整个文件
fs.readFile(path[, options], callback)
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});
- 精细读取文件
fs.read(fd, buffer, offset, length, position, callback((err, bytesRead, buffer)))
const fs=require('fs');
const path=require('path');
fs.open(path.join(__dirname,'1.txt'),'r',0o666,function (err,fd) {
console.log(err);
let buf = Buffer.alloc(6);
fs.read(fd,buf,0,6,3,function(err, bytesRead, buffer){
console.log(bytesRead);//6
console.log(buffer===buf);//true
console.log(buf.toString());
})
})
写入
- fs.writeFile(file, data[, options], callback)
data:string|buffer
const data = new Uint8Array(Buffer.from('Hello Node.js'));
fs.writeFile('message.txt', data, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
- fs.write(fd, string[, position[, encoding]], callback)
data:string|buffer
const fs=require('fs');
const path=require('path');
fs.open(path.join(__dirname,'1.txt'),'w',0o666,function (err,fd) {
console.log(err);
let buf=Buffer.from('一川烟草,满城风絮,梅子黄时雨');
fs.write(fd,buf,3,6,0,function(err, bytesWritten, buffer){
console.log(bytesWritten);//6
console.log(buffer===buf);//true
console.log(buf.toString());//
})
})
追加
fs.appendFile(path, data[, options], callback)
- path : 目标路径
- data :写入内容,string或者buffer
- options:
- flags:默认为’a’ ;
- encoding: 默认编码为utf8
- mode: 权限编码,默认读写,无执行
function saveLog(logpath, content) {
debug(logpath)
content = `\n ${(new Date()).toString()} \n ${content} \n`
fs.appendFile(logpath, content, {
flags: 'a+',
encoding: 'utf8',
mode: 0o666
}, err => {
if (err) {
let errStr = util.inspect(err)
debug(chalk.red(`save log error: \n ${errStr}`))
}
})
目录
创建
fs.mkdir(path[, options], callback)
- npm包: mkdirp,递归创建目录及其子目录
删除
fs.rmdir(path, callback)
只能用来删除空目录!!! 如有子目录或包含文件,则需要先删除子目录和文件,否则报错
递归删除
const fs = require('fs')
const path = require('path')
const rootDir = path.resolve(__dirname, 'dirr')
function delDirrSync(dirPath) {
let stats = fs.statSync(dirPath)
if (stats.isFile()) {
fs.unlinkSync(dirPath)
} else if (stats.isDirectory()) {
let files = fs.readdirSync(dirPath)
if (files.length === 0) {
fs.rmdirSync(dirPath)
} else {
files.map(item => {
let filepath = path.join(dirPath, item)
delDirrSync(filepath)
})
delDirrSync(dirPath)
}
}
}
delDirrSync(rootDir)
异步删除
const fs = require('fs')
const path = require('path')
const rootDir = path.resolve(__dirname, 'dirr')
function delDirAsync(dirPath) {
return new Promise((resolve, reject) => {
fs.access(dirPath, err => {
if (err) {
reject(err)
} else {
fs.stat(dirPath, (err, stats) => {
if (stats.isFile()) {
fs.unlink(dirPath, err => {
if (!err) {
console.log(dirPath)
resolve(dirPath)
}
else reject(err)
})
} else {
fs.readdir(dirPath, (err, files) => {
if (err) {
reject(err)
} else {
Promise.all(
files.map(file => {
let filePath = path.join(dirPath, file)
return delDirAsync(filePath)
})
).then(() => {
console.log(dirPath)
fs.rmdir(dirPath, resolve)
}
)
}
})
}
})
}
})
})
}
delDirAsync(rootDir)
读取
fs.readdir(path[, options], (error,files)=>{})
读取文件夹下的所有内容,包括子文件夹和文件,files是数组类型
移动
fs.rename(oldPath, newPath, error=>{})
监视
自动路由、自动化构建工具等可能会用到
文件
- fs.watchFile(path,(curr,prev)=>{})
- fs.watch()
文件夹
- fs.watch()
fs.watchFile('message.text', (curr, prev) => {
console.log(`the current mtime is: ${curr.mtime}`);
console.log(`the previous mtime was: ${prev.mtime}`);
});
权限
此操作类似linux中更改档案权限,有关linux的权限机制具体可参照学习笔记-linux权限控制
fs.chmod(path, mode, callback)
fs.chown(path, uid, gid, callback)
读写流
常用flags
- 'r' - 以只读方式打开文件,若文件不存在则报错。
- 'r+' - 以读写方式打开文件,若文件不存在则报错。
- 'rs+' 在同步模式下,以读写方式打开文件
- 'w' - 以写方式打开文件,若文件不存在则创建
- 'wx' - 以写方式打开文件,若文件不存在则抛出异常.
- 'w+' - 以读写方式打开文件,若文件不存在则创建,相反则清空文件.
- 'wx+' - 以读写方式打开文件,若文件不存在则抛出异常.
- 'a' - 以追加方式打开文件,若文件不存则创建文件
- 'ax' - 以追加方式打开文件,若文件不存则抛出异常.
- 'a+' - 以追加和读方式打开文件,若文件不存则创建文件
- 'ax+' - 以追加和读方式打开文件,若文件不存则失败
- x 排他方式
- r 读取
- w 写入
- s 同步
-
- 额外(相反)操作
path模块
- path.join()
- path.resolve()
- path.dirname(path)
- path.extname(path): 获取文件拓展名
- path.basename(path[, ext]):获取文件名不含路径