监控文件夹的变化
fs模块提供了FSWatcher类来辅助我们进行监控文件夹。
fs.watch(filename[, options][, listener])
示例代码:
const fs = require("fs");
// 监听文件夹变化:
// 1.
// 启动监听文件夹
let watcher = fs.watch(__dirname);
// 监听改变的事件
watcher.on('change', function(eventType, fileName){
console.log('change: ', eventType, fileName);
});
// 关闭监听
setTimeout(() => {
watcher.close(); // 实际: 关闭监听
}, 10000);
// 2.
let watcher2 = fs.watch(__dirname, function(eventType, fileName){
console.log('callback: ', eventType, fileName);
});
// 关闭监听
setTimeout(() => {
watcher2.close(); // 实际: 关闭监听
}, 10000);
读取文件下面所有的文件和文件夹
示例代码:
const fs = require("fs");
const path = require("path");
// 读取一个路径,返回路径下面所有的文件或文件夹的名字
fs.readdir(__dirname, (err, files)=>{ // 异步方式
// console.log(files);
files.forEach((item, index)=>{
fs.stat(path.join(__dirname, item), (err, stat)=>{
if(err){
console.log("error!");
return;
}
stat.isFile() ? console.log("file", item) : console.log("dir", item);
// console.log(stat);
}); // 判断是文件还是文件夹
});
});
读取文件
一次性读取小文件
示例代码:
const fs = require("fs");
const path = require("path");
// 读取当前文件的内容,此处设置了编码方式为utf8
// 同步方法,即当程序到此处时,整个程序会等文件读完,将内容赋值给filecontent
// ps:该方法会一次把整个文件读完(读到内存里),当遇到很大的文件时。。故只适合小文件。
let filecontent = fs.readFileSync(__filename, {
encoding: 'utf8'
});
console.log(filecontent);
// 异步读取文件的方法:
// 主线程继续执行后续代码,线程池的线程读取文件内容。文件内容读取成功后,调用回调函数。
// 仅用于读取小文件。
let indexJSFileName = path.join(__dirname, "index.js");
fs.readFile(indexJSFileName, {
encoding: "utf8"
}, function(err, data){
console.log("文件读取完毕,执行回调函数。。");
if(err){
console.log("出现读取异常: ", err);
return;
}
console.log(data);
});
console.log("主线程继续执行。。。");
读取大文件
采用path.createReadStream
步骤:
- 创建一个可读流
- 打开时触发open事件
- 来数据时触发data事件
- 读完时触发end事件
示例代码:
const fs = require("fs");
const path = require("path");
let fileName = path.join(__dirname, "a.pdf");
// 创建一个可读取的流
// let stream = fs.createReadStream(fileName, {
// encoding: "utf8"
// });
let stream = fs.createReadStream(fileName);
// 当流的管道建立后并打开时,触发open事件
stream.on("open", function(fd){
console.log("管道建立,并打开:fd", fd);
});
// data:当数据来的时候会触发这个事件
let i = 0;
stream.on("data", function(trunk){
console.log("编号%d", i, trunk);
i++;
});
stream.on("end", function(){
console.log("数据读取完毕!");
});
写入文件
一次性写入少量文件
示例代码:
const fs = require("fs");
const path = require("path");
let aFilePath = path.join(__dirname, 'a.txt');
// 异步写入方式。
fs.writeFile(aFilePath, "你好,学习nodejs", function(err){
if(err){
console.log(err);
return;
}
console.log("正常写入");
});
// 同步写入
// fs.writeFileSync(aFilePath, "hello~");
流的方式写入
const fs = require("fs");
const path = require("path");
// 用可写流,往 b.txt文件中写入100个字符串
let aFileName = path.join(__dirname, 'a.txt');
let stream = fs.createWriteStream(aFileName, {
flags: 'a'
}); // 用追加的方式创建一个可写流
stream.on('open', function(fd){
console.log("可写流打开 ", fd);
});
stream.on("close", function(){
console.log("可写流关闭。");
});
// 往可写流里写入数据
for(let i = 0; i<100; i++){
stream.write("learn!\n");
}
// 调用end方法,结束可写流
// stream.end(); // 内部不写也可以
stream.end("结尾!");
大文件的复制
1.通过读写流方式
原理图:
参考代码:
const fs = require("fs");
const path = require("path");
let srcFile = path.join(__dirname, "a.pdf");
let destFile = path.join(__dirname, "b.pdf");
let rs = fs.createReadStream(srcFile); // 创建可读流
let ws = fs.createWriteStream(destFile); // 创建写流
rs.on("open", function(fd){
console.log("可是读取文件内容。。。");
});
rs.on("close", function(){
console.log("读取结束!");
});
rs.on("data", function(trunk){
if (ws.write(trunk) == false){ // 如果返回true表示还可以写,如果返回false表示不能再写了。
// 缓冲区满了,不能再写了
rs.pause(); // 让可读流暂停读取数据
}
});
ws.on("drain", function(){
// 可写流数据可以继续写入时,让可读流继续读数据。
rs.resume();
});
2.通过管道的方式
示例代码:
const fs = require("fs");
const path = require("path");
let srcFile = path.join(__dirname, 'a.pdf'); // 源文件
let destFile = path.join(__dirname, 'c.pdf'); // 目标文件
let rs = fs.createReadStream(srcFile); // 可读流
let ws = fs.createWriteStream(destFile); // 可写流
rs.pipe(ws);
递归读取一个文件夹下面所有的文件名字(包括子文件夹里的)
参考代码:
// 实现:
// 给一个名字:(注意检查名字是否合法,此处写的就是合法的,未对给定名字的合法性进行判断)
// 如果名字是文件,就直接打印
// 如果名字是文件夹,就读取其下的内容
//(采用递归的方式实现)
// 引入需要的内置模块
const fs = require("fs");
const path = require("path");
// let dirName = __dirname; // __dirname 当前工作目录
let dirName = "./test";
readDir(dirName); // 获取该目录下所有的文件及文件夹名字
function readDir(dirN){
fs.readdir(dirN, (err, files)=>{
if(err){
console.log(err);
return;
}
files.forEach((item, index)=>{
// 对于每一个item,组装其完整路径
comFileName = path.join(dirN, item);
// 判断每一个comFileName是文件还是文件夹,是文件就输出文件名,是文件夹就进入文件夹读取输出其下的文件名
fs.stat(comFileName, (err, stats)=>{
if(err){
console.log(err);
return;
}
// 通过stat的isFile方法确定是路径还是文件夹
// stats.isFile() ? console.log("file:", item, " ", comFileName) : console.log("dir:", item, " ", comFileName);
if(stats.isFile()){
console.log(item);
}else{
readDir(path.join(dirN, item)); // 如果是文件夹继续读取里面的
}
});
});
});
}
待改进:
- 以树状图的方式显示一个文件夹内部的结构