文件系统时nodejs中至关重要的一个模块,它使得JavaScript具备了操作文件的能力。对于所有文件或目录的操作fs都提供了同步和异步两种操作方式。另外nodejs也提供了文件流的处理。想要熟练掌握nodejs中文件的处理需要先了解以下几个概念:字符,字符集,字符编码,文件流,buffer。
- 字符:字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
- 字符集和字符编码:字符集就是各种字符的集合,而字符编码就是为字符集中每个字符规定个二进制数的一套规则,如我们常用的ASCALL,Unicode,UTF-8等。简单的来说字符集就是一套集合,字符编码就是一种集合对应的规则。
- ASCALL编码:
- Unicode:
- UTF-8
- 文件流:从字面意思可以看出,文件流其实就是把文件当作水流一样进行处理。为何需要文件流呢,这个就要说到计算机等I/O处理了,大文件的打开和处理对于计算机I/O的消耗是很大的,随着互联网的发展几十几百G的文件很常见但是几百G的内存成本却很大,因此对文件的处理就需要流来进行,下载或上传时候把一个大文件分成若干份像水流一样进行传输。
- Buffer:前端在刚接触buffer的时可能会把他当作字符串处理,这一点是不可取的,buffer和字符串有本质的区别,buffer是二进制数据流。
文件
nodejs中提供文件服务的是fs模块,他能够实现文件、目录的增删改查,以及文件的信息获取。
- 文件目录的增删改查,fs对于目录的处理基本功能都有实现,新增(mkdir),删除(rmdir),查询(readdir)下面简单介绍下这些API的同步使用。
let fs = require("fs"); const newDir = __dirname + '/fsdir'; if(fs.existsSync(newDir)){ console.log('dir is exists,delete dir!') fs.rmdirSync(newDir); const currentFiles = fs.readdirSync(__dirname); console.log('query current dir file list:') currentFiles && currentFiles.forEach(file=>{ console.log(file) }) return } // 新建目录,新建前需要判断是否存在,如果存在还新建则会报错 fs.mkdirSync(newDir)
- 文件的增删改查,fs中具有对文件的新增(writeFile),删除(rm),重命名(rename),读取文件(readFile)内容以及复制(copyFile)等常用功能,下面简单介绍下这些API的同步使用。
let fs = require("fs") const userFile = newDir + '/user.json'; console.log(userFile) if (fs.existsSync(userFile)) { console.log('user.json file is exists!') const f = `${newDir}/${Date.now()}.json` const fcp = `${newDir}/${Date.now()}cp.json` const cpf = fs.copyFileSync(userFile, fcp); const rnf = fs.renameSync(userFile, f); const fileBuff = fs.readFileSync(f); } else { fs.writeFileSync(userFile, '{"name":"json"}'); }
对于文件的直接操作通常用在日常的脚本处理中,在生产服务器上考虑到性能等原因使用文件流来处理文件是更好的选择。
应用
根据fs的功能我们实现一个简单的文件复制的脚本
- 功能描述:脚本接受两个参数src目录或文件,des目录或文件,将dest代表的目录或文件完整的复制到dest目录或文件中
- 实现分析:首先需要判断输入的src是否存在,如果存在则判断是文件还是目录,如果是目录则执行目录的逻辑,如果是文件则执行文件的复制逻辑。
- 大概代码如下,详细请看
const fs = require('fs'); const argvs = process.argv; const src = __dirname + '/' + argvs[2]; const dest = __dirname + '/' + argvs[3]; if (!fs.existsSync(src)) { console.log('file is not exists!') return } const stat = fs.lstatSync(src); const handlerRemoveDir = (dir) => { let files = fs.readdirSync(dir) **** } if (stat.isDirectory()) { if (fs.existsSync(dest)) { console.log("目标目录已存在,请重新输入!") handlerRemoveDir(dest) return } fs.mkdirSync(dest); const files = fs.readdirSync(src); console.log(files) **** console.log('目录复制成功!') } if (stat.isFile()) { if (fs.existsSync(dest)) { console.log("目标文件已存在,请重新输入!") return } fs.copyFileSync(src, dest); console.log('文件复制成功!') }
总结
nodejs对于前端来说难点不是他各个的模块的API,这些API和前端使用的JavaScript语法高度类似,基本看下文档就能使用。真正的难点是这些API背后的一些知识原理,就如本章描述的fs模块,他背后蕴含了计算机对于文件的许多知识内容。