node.js--fs(文件系统模块):查看文件状态、读文件、写文件、追加写入、分批读取、分批写入、拷贝文件、pipe拷贝文件

目录

1.查看文件状态

2.读取文件

3.文件写入

4. Buffer

5.追加写入

6.分批读取和分批写入

7.拷贝文件

8. pipe拷贝文件

9.示例

10. 创建目录

11. 读取目录

12. 删除目录

13. 利用NodeJS生成项目模板


fs模块是Nodejs官方提供的、用来操作文件的模块。它提供了一些列的方法和属性,用来满足用户对文件的操作需求

1.查看文件状态

a. fs.stat(path[, options], callback)  异步方法 :

let fs = require("fs");

console.log("1");

//获取当前文件的路径
// console.log(__filename);

//获取当前文件所属的文件夹
// console.log(__dirname);

fs.stat(__filename, function(err, stats) {
    // console.log("3");
    // console.log(err);
    // birthtime: 文件的创建时间
    // mtime: 文件中内容发生变化, 文件的修改时间
    console.log(stats);

    if (stats.isFile()) {
        console.log("当前路径对应的是一个文件");
    } else if (stats.isDirectory()) {
        console.log("当前路径对应的是一个文件夹");
    }
});
console.log("2");

b.fs.statSync(path[, options])  同步方法:

let fs = require("fs");

console.log("1");

//获取当前文件所属的路径
// console.log(__filename);

// 获取当前文件所属路径的文件夹
// console.log(__dirname);


console.log("2");


let stats = fs.statSync(__filename);
console.log(stats);


2.读取文件

fs.readFile(path[, options], callback)  异步方法:

  • path:必选参数,文件路径
  • options:可选参数,字符串,表示以什么编码格式读取
  • callback:必选参数,文件读取完成后,通过回调函数拿到读取的结果
let fs = require("fs");
// let path = require("path"); // 方式2

// 方式2 拿到需要读取的文件路径 
// let str = path.join(__dirname, "./readMe.txt");
//读取文件
// fs.readFile(str, "utf8", function(err, data){});

// 方式1读取文件
fs.readFile('./readMe.txt', "utf8", function(err, data) {
    if (err) {
        throw new Error("读取文件失败");
    }
    console.log(data.toString());
});

fs.readFileSync(path[, options])   同步方法:

let fs = require("fs");
// let path = require("path"); // 方式2

// 方式2-拿到需要读取的文件路径
// let str = path.join(__dirname, "./readMe.txt");
// let data = fs.readFileSync(str, "utf8");

// 方式1-读取文件
let data = fs.readFileSync('./readMe.txt', "utf8");
console.log(data);

注意点:

  • 没有指定第二个参数, 默认会将读取到的数据放到Buffer中
  • 第二个参数指定为utf8, 返回的数据就是字符串


3.文件写入

fs.writeFile(file, data[, options], callback)  异步方法:

  •  file:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径
  • data:必选参数,表示要写入的内容
  • options:可选参数,表示以什么格式写入文件,默认utf-8
  • callback:必选参数,文件写入完成后,通过回调函数拿到读取的结果
let fs = require("fs");
// let path = require("path");// 方式2 

// 方式2 拼接写入的路径
// let str = path.join(__dirname, "./writeMe.txt");
/*
fs.writeFile(str, "百度 www.baidu.com", "utf-8", function (err) ...
 或如下写法
*/
// let buf = Buffer.from("www.baidu.com");
// fs.writeFile(str, buf, "utf-8", function(err) {...


// 方式1 写入数据
/*
fs.writeFile(str, "百度 www.baidu.com", "utf-8", function (err) ...
 或如下写法
*/
let buf = Buffer.from("www.baidu.com");
fs.writeFile('./writeMe.txt', buf, "utf-8", function(err) {
    if (err) {
        throw new Error("写入数据失败");
    } else {
        console.log("写入数据成功");
    }
});

 fs.writeFileSync(file, data[, options])  同步方法:

let fs = require("fs");
// let path = require("path");//方式2

//方式2
// 拼接写入的路径
// let str = path.join(__dirname, "./writeMe.txt");
// let res = fs.writeFileSync(str, "百度 www.baidu.com", "utf-8");

// 2.写入数据
let res = fs.writeFileSync('./writeMe.txt', "淘宝 www.taobao.com", "utf-8");


4. Buffer

Buffer是NodeJS全局对象上的一个类, 是一个专门用于存储字节数据的类

NodeJS提供了操作计算机底层API, 而计算机底层只能识别0和1,所以就提供了一个专门用于存储字节数据的类

4.1 创建一个指定大小的Buffer:

Buffer.alloc(size[, fill[, encoding]])

  • size   新的 Buffer 所需的长度。
  • fill  用于预填充新 Buffer 的值。 默认值: 0
  • encoding   如果 fill 是字符串,则这就是它的编码。 默认值: 'utf8'

如果 size 大于 buffer.constants.MAX_LENGTH(单个 Buffer 实例允许的最大大小) 或小于 0,则抛出  ERr_INVALID_ARG_VALUE 

如果指定了 fill,则分配的 Buffer 将通过调用 buffer.fill(fill) 进行初始化。

 如果同时指定了 fillencoding,则分配的 Buffer 将通过调用  buffer.fill(fill,encoding) 进行初始化

如果 size 不是数值,则会抛出 TypeError

示例:

let buf = Buffer.alloc(5);
console.log(buf); // <Buffer 00 00 00 00 00>
// 注意点: 通过console.log();输出Buffer. 会自动将存储的内容转换成16进制再输出

let buf1 = Buffer.alloc(5, 17);
console.log(buf1);

4.2 根据数组/字符串创建一个Buffer对象

使用 0255 范围内的字节 array 分配新的 Buffer。 该范围之外的数组条目将被截断以符合它。 

Buffer.from(string[, encoding])

let buf = Buffer.from("abc");
console.log(buf); // <Buffer 61 62 63>

let buf1 = Buffer.from([1, 3, 5]);
console.log(buf1);
console.dir(buf1);
buf1[0] = 6;
console.log(buf1);

Buffer的本质其实就是一个数组

4.3 将二进制数据转换成字符串:

返回: <string> 转换后的字符串数据。

buf.toString();
let buf = Buffer.from([97, 98, 99]);
console.log(buf);
console.log(buf.toString());

4.4 往Buffer中写入数据:

string <string> 要写入 buf 的字符串。

offset <integer> 开始写入 string 之前要跳过的字节数。默认值: 0。

length <integer> 要写入的字节数。默认值: buf.length - offset。

encoding <string> string 的字符编码。默认值: 'utf8'。

返回: <integer> 已写入的字节数。

buf.write(string[, offset[, length]][, encoding])

let buf = Buffer.alloc(5); // <Buffer 00 00 00 00 00>
console.log(buf); // <Buffer 00 00 00 00 00>
buf.write("abcdefg");
console.log(buf); //<Buffer 61 62 63 64 65>
console.log(buf.toString()); //abcde

let buf = Buffer.alloc(5);
console.log(buf);
buf.write("abcdefg", 2);
console.log(buf);
console.log(buf.toString());

let buf = Buffer.alloc(5);
console.log(buf);
buf.write("abcdefg", 2, 2);
console.log(buf);

4.5 从指定位置截取新Buffer:

start <integer> 新 Buffer 开始的位置。默认值: 0。

end <integer> 新 Buffer 结束的位置(不包含)

buf.slice([start[, end]])

let buf1 = Buffer.from("abcdefg");
let buf2 = buf1.slice();
console.log(buf2);
console.log(buf2.toString());

let buf1 = Buffer.from("abcdefg");
let buf2 = buf1.slice(2);
console.log(buf2);
console.log(buf2.toString());

let buf1 = Buffer.from("abcdefg");
let buf2 = buf1.slice(2, 4);
console.log(buf2);
console.log(buf2.toString());

 4.6 检查是否支持某种编码格式

Buffer.isEncoding(encoding)

let res = Buffer.isEncoding("gbk");
console.log(res);

4.7 检查是否是Buffer类型对象

Buffer.isBuffer(obj)

let obj = {};
let res = Buffer.isBuffer(obj);
console.log(res);//false
let obj = Buffer.alloc(5);
let res = Buffer.isBuffer(obj);
console.log(res); //true

4.8 获取Buffer实际字节长度

Buffer.byteLength(string[, encoding])

注意点: 一个汉字占用三个字节

let buf = Buffer.from("123");
let res = Buffer.byteLength(buf);
console.log(res); //3
console.log(buf.length); //3
let buf = Buffer.from("人生");
let res = Buffer.byteLength(buf);
console.log(res); //6
console.log(buf.length); //6

4.9 合并Buffer中的数据

Buffer.concat(list[, totalLength])

let buf1 = Buffer.from("123");
let buf2 = Buffer.from("abc");
let buf3 = Buffer.from("xxx");
let res = Buffer.concat([buf1, buf2, buf3]);
console.log(res);
console.log(res.toString());


5.追加写入

fs.appendFile(path, data[, options], callback) 异步方法:

let fs = require("fs");
// let path = require("path");// 方式2

// 方式2
// 拼接写入的路径
// let str = path.join(__dirname, "./writeMe.txt");
// fs.appendFile(str, " BAT", "utf8", function(err) {...

// 方式1
// 开始追加数据
fs.appendFile('./writeMe.txt', " BAT", "utf8", function(err) {
    if (err) {
        throw new Error("追加数据失败");
    } else {
        console.log("追加数据成功");
    }
});

fs.appendFileSync(path, data[, options]) 同步方法:

let fs = require("fs");
// let path = require("path"); // 方式2

// 方式2
// // 拼接写入的路径
// let str = path.join(__dirname, "./writeMe.txt");
// fs.appendFileSync(str, " AAA", "utf8");

// 方式1
// 开始追加数据
fs.appendFileSync('./writeMe.txt', " AAA", "utf8");


6.分批读取和分批写入

  • 前面讲解的关于文件写入和读取操作都是一次性将数据读入内存或者一次性写入到文件中
  • 但是如果数据比较大, 直接将所有数据都读到内存中会导致计算机内存爆炸,卡顿,死机等
  • 所以对于比较大的文件我们需要分批读取和写入

fs.createReadStream(path[, options])--分批读取:

let fs = require("fs");
// let path = require("path"); // 方式2

// 方式2
// 拼接读取的路径
// let str = path.join(__dirname, "./readMe.txt");
// let readStream = fs.createReadStream(str, { encoding: "utf8", highWaterMark: 1 });
//...


// 方式1
// 创建一个读取流
// createReadStream(path[, options])
// highWaterMark  每次读取多少个字节
let readStream = fs.createReadStream('./readMe.txt', { encoding: "utf8", highWaterMark: 1 });

// 3.添加事件监听
readStream.on("open", function() {
    console.log("表示数据流和文件建立关系成功");
});
readStream.on("error", function() {
    console.log("表示数据流和文件建立关系失败");
});
readStream.on("data", function(data) {
    console.log("表示通过读取流从文件中读取到了数据", data);
});
readStream.on("close", function() {
    console.log("表示数据流断开了和文件的关系, 并且数据已经读取完毕了");
});

fs.createWriteStream(path[, options])--分批写入

let fs = require("fs");
// let path = require("path"); // 方式2


// 方式2
// 拼接写入的路径
// let str = path.join(__dirname, "./writeMe.txt");
// let writeStream = fs.createWriteStream(str, { encoding: "utf8" });
// ...


// 方式1
// 2.创建一个写入流 createWriteStream(path[, options])
let writeStream = fs.createWriteStream('./writeMe.txt', { encoding: "utf8" });

// 3.监听写入流的事件
writeStream.on("open", function() {
    console.log("表示数据流和文件建立关系成功");
});
writeStream.on("error", function() {
    console.log("表示数据流和文件建立关系失败");
});
writeStream.on("close", function() {
    console.log("表示数据流断开了和文件的关系");
});

//需要写入的数据 
let data = "www.baidu.com";

let index = 0;

let timerId = setInterval(function() {
    //每隔一秒就取出一个
    let ch = data[index];
    index++;

    //写入数据
    writeStream.write(ch);

    console.log("本次写入了", ch);

    //判断是否写完
    if (index === data.length) {
        clearInterval(timerId);
        //写入结束
        writeStream.end();
    }
}, 1000);


7.拷贝文件

let fs = require("fs");
// let path = require("path"); // 方式2

// 方式2
// 生成读取和写入的路径
// let readPath = path.join(__dirname, "./readMe.txt");
// let writePath = path.join(__dirname, "./writeMe.txt");
// let readStream = fs.createReadStream(readPath);
// let writeStream = fs.createWriteStream(writePath);

// 2.创建一个读取流
let readStream = fs.createReadStream('./readMe.txt');

// 3.创建一个写入流
let writeStream = fs.createWriteStream('./writeMe.txt');

// 4.监听读取流事件
readStream.on("open", function() {
    console.log("表示数据流和文件建立关系成功");
});
readStream.on("error", function() {
    console.log("表示数据流和文件建立关系失败");
});
readStream.on("data", function(data) {
    // console.log("表示通过读取流从文件中读取到了数据", data);
    writeStream.write(data);
});
readStream.on("close", function() {
    console.log("表示数据流断开了和文件的关系, 并且数据已经读取完毕了");
    writeStream.end();
});

// 5.监听写入流的事件
writeStream.on("open", function() {
    console.log("表示数据流和文件建立关系成功");
});
writeStream.on("error", function() {
    console.log("表示数据流和文件建立关系失败");
});
writeStream.on("close", function() {
    console.log("表示数据流断开了和文件的关系");
});


8. pipe拷贝文件

let fs = require("fs");
// let path = require("path");// 方式2

// 方式2
// 生成读取和写入的路径
// let readPath = path.join(__dirname, "./readMe.txt.mp4");
// let writePath = path.join(__dirname, "./writeMe.txt.mp4");
// let readStream = fs.createReadStream(readPath);
// let writeStream = fs.createWriteStream(writePath);

//方式1
// 2.创建一个读取流
let readStream = fs.createReadStream("./readMe.txt");

// 3.创建一个写入流
let writeStream = fs.createWriteStream("./writeMe.txt");

// 利用读取流的管道方法来快速的实现文件拷贝
readStream.pipe(writeStream);

9.示例

示例1

//1. 导入模块
const fs = require('fs');

// 2.读取文件内容
fs.readFile('./成绩.txt','utf8',function(err,dataStr){

    // 3.判断是否读取成功
    if(err){
        return console.log('读取文件失败',err);
    }
    // console.log('读取文件成功',dataStr);

    // 4.将读取到的内容进行处理
    const arrOld = dataStr.split(' ');
    const arrNew = [];
    arrOld.forEach(item => {
        arrNew.push(item.replace('=',':'));
    });
    //将新数组中的每一项进行合并,并得到一个新的字符串
    const newStr = arrNew.join('\r\n');//回车换行
    
    //将处理好的数据写入新文件里
    fs.writeFile('./新成绩.txt',newStr,function(err){
        if(err){
            return console.log('写入文件失败',err.message);
        }
        console.log('成绩写入成功');
    });
})


10. 创建目录

fs.mkdir(path[, mode], callback)   异步操作方法

let fs = require("fs");
let path = require("path");

// 创建的路径
let str = path.join(__dirname, "abc");

fs.mkdir(str, function(err) {
    if (err) {
        throw new Error("创建目录失败");
    } else {
        console.log("创建目录成功");
    }
});

fs.mkdirSync(path[, mode])  同步操作方法

let fs = require("fs");
let path = require("path");

// 创建的路径
let str = path.join(__dirname, "abc");
fs.mkdirSync(str);


11. 读取目录

fs.readdir(path[, options], callback)  异步操作方法

fs.readdir(__dirname, function(err, files) {
    if (err) {
        throw new Error("读取目录失败");
    } else {
        // console.log(files);
        // 遍历取出每一个文件和文件夹
        files.forEach(function(obj) {
            // console.log(obj);
            //获得所有文件的路径
            let filePath = path.join(__dirname, obj);
            // console.log(filePath);
            //获取文件的状态
            let stats = fs.statSync(filePath);
            if (stats.isFile()) {
                console.log("是一个文件", obj);
            } else if (stats.isDirectory()) {
                console.log("是一个目录", obj);
            }
        });
    }
})

fs.readdirSync(path[, options])  同步操作方法


12. 删除目录

fs.rmdir(path, callback)  异步操作方法

let fs = require("fs");
let path = require("path");

// 创建的路径
let str = path.join(__dirname, "abc");


fs.rmdir(str, function(err) {
    if (err) {
        throw new Error("删除目录失败");
    } else {
        console.log("删除目录成功");
    }
});

fs.rmdirSync(path)  同步操作方法

let fs = require("fs");
let path = require("path");

// 创建的路径
let str = path.join(__dirname, "abc");
fs.rmdirSync(str)


13. 利用NodeJS生成项目模板

let fs = require("fs");
let path = require("path");

class CreateProject {
    constructor(rootPath, projectName) {
        this.rootPath = rootPath;
        this.projectName = projectName;
        this.subFiles = ["images", "css", "js", "index.html"];
    }
    initProject() {
        // 1.创建站点文件夹
        let projectPath = path.join(this.rootPath, this.projectName);
        fs.mkdirSync(projectPath);
        // 2.创建子文件和子目录
        this.subFiles.forEach(function(fileName) {
            //判断是文件还是文件夹
            if (path.extname(fileName) === "") {
                let dirPath = path.join(projectPath, fileName);
                fs.mkdirSync(dirPath);
            } else {
                let filePath = path.join(projectPath, fileName);
                fs.writeFileSync(filePath, "");
            }
        })
    }
}

let cp = new CreateProject(__dirname, "taobao");
cp.initProject();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白小白从不日白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值