【node.js】基础之修改文件

node.js 基础(一)

node.js是什么?
上面这句话的意思就是:Node.js 是一个开源的,跨平台的javascript运行环境。通俗的说就是一个应用程序或者说是一个软件,可以运行javascript。
Node.js的作用:
  1. 开发服务器应用。 将数据返回给用户。

  2. 开发工具类应用: webpack,vite,babel,提高开发效率。

  3. 开发桌面端应用: vscode,Figma,Postman 。他们是借助electron开发的,electron是通过node.js开发的。

Node.js 下载地址:

上链接:https://nodejs.org/en/download。

Node.js初体验:

运行一个JS文件:

命令: node xxxx

Node.js注意事项

浏览器中的javascript:

Node.js中的javascript:

由上图我们可以发现node的API实际上是没有包含BOM , DOM ,AJAX, STORAGE等的。但是由两个共同的API,console和定时器。所以node是不能操作BOM和DOM的。

node的顶级对象:global ,相当于js中的window

gloab: 顶级对象

gloabThis: 顶级指向对象 是ES2020指向顶级对象

global和globalThis 两个是相等的。

复制代码
// BOM
console.log(window)

// DOM
console.log(navigator)
console.log(history)
 console.log(location)

// 定时器和console是可以用的

// node的顶级对象是global , globalThis 相当于js环境的window对象。
console.log(global)
console.log(globalThis)  //ES2020指向顶级对象

console.log(global === globalThis)
Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

Buffer 大小固定不能调整,性能较好,可以直接对计算机内存进行操作

Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。

目前支持的字符串编码包括:

  • ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
  • utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
  • utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
  • ucs2 - utf16le 的别名。
  • base64 - Base64 编码。
  • latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
  • binary - latin1 的别名。
  • hex - 将每个字节编码为两个十六进制字符。
创建Buffer类
  • Buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0

  • Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据

  • Buffer.allocUnsafeSlow(size)

  • Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)

  • Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。

  • Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例

  • Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例

    // 创建一个长度为 10、且用 0 填充的 Buffer。
    // const buf1 = Buffer.alloc(10);
    // console.log("buf1", buf1)

    // 创建一个长度为 10、且用 0x1 填充的 Buffer。
    // const buf2 = Buffer.alloc(10, 1);
    // console.log("buf2", buf2)

    // 创建一个长度为 10、且未初始化的 Buffer。
    // 这个方法比调用 Buffer.alloc() 更快,
    // 但返回的 Buffer 实例可能包含旧数据,
    // 因此需要使用 fill() 或 write() 重写。
    // const buf3 = Buffer.allocUnsafe(10);
    // console.log("buf3", buf3)

    // 打印出来的值每次都不一样
    // const buf77 = Buffer.allocUnsafe(10000);
    // console.log("buf77", buf77)

    // 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
    // const buf4 = Buffer.from([1, 2, 3]);
    // console.log("buf4", buf4)

    // 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
    // const buf5 = Buffer.from('tést');

    // 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
    // const buf6 = Buffer.from('tést', 'latin1');

读写Buffer

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

参数描述如下:

  • string - 写入缓冲区的字符串。
  • offset - 缓冲区开始写入的索引值,默认为 0 。
  • length - 写入的字节数,默认为 buffer.length
  • encoding - 使用的编码。默认为 'utf8' 。

示例:writeBuffer.js

fs模块

可以实现与硬盘的交互,例如文件的创建、删除、重命名、移动,还有文件内容的写入、读取及文件夹的相关操作。

文件写入异步
复制代码
fs.writeFile(file, data[, options], callback)

参数

参数使用说明如下:

  • file - 文件名。
  • data - 待写入的数据。
  • options - 选项设置(可选)。
  • callback - 回调函数。

返回值: undefined

文件写入同步

fs.readFileSync('input.text')

复制代码
// 需求1:创建一个文件,写入内容:  下班了吗?

const fs = require('fs');

// fs.writeFile('./哈哈.txt', '下班了吗?', err => {
//     if(err){
//         console.log('写入失败')
//         return
//     }

//     console.log('写入成功')
// });


// console.log(111111)
// 上述为异步线程


// 同步线程
// fs.writeFileSync("./同步哈哈.txt", "hhhhhhhhh");

// console.log(1111)


// 需求2:在哈哈文件里,再写入一段话,还没有下班

// fs.appendFile("./哈哈.txt", "\r\n还没下班", err => {

//     if(err){
//         console.log('写入失败')
//         return
//     }

//     console.log('写入成功')
// })

// fs.appendFileSync("./哈哈.txt", "\r\n我也还没有下班")


// 使用wirtFile追加写入

fs.writeFile('./哈哈.txt', '\r\n什么时候下班呀????', {flag: 'a'}, err => {
    if(err){
        console.log('写入失败')
        return
    }

    console.log('写入成功')
});

// 增加配置项

// fs.writeFile('./哈哈.txt', '\r\n到底什么时候下班呀?', {flag: 'a'},err => {
//     if(err){
//         console.log('写入失败')
//         return
//     }

//     console.log('写入成功')
// });

什么时候需要追加写入呢?

写入程序日志时,记录用户访问时间等。

fs流式写入

流式写入式一种将数据分批次写入文件的操作方式。

与文件写入相比,‌流式写入的主要区别在于数据处理的方式和速度。‌在流式写入操作中,‌数据不需要一次性存储在内存中,‌而是逐步写入磁盘。‌这种方式可以在处理大量数据时减少内存的占用,‌从而使程序更加稳定。‌流式写入还可以实现边读边写的操作,‌即当数据量非常大时,‌可以逐步地读取数据,‌然后将其立即写入文件,‌这样可以在处理数据时避免数据过多而导致程序崩溃。‌

语法:

fs.createWriteStream(path[, options])

writeFile与createWriteStream的区别。

writeFile单次写入,写入之后立马关闭通道,适合写入频次较少的操作。

createWriteStream适合于频次较多的操作,createWriteStream创建一个通道之后,写入一次之后,不会关闭通道,减少了打开关闭文件的次数,在close之前可以持续的写入。

使用createWriteStream追加内容怎么处理呢?

文件写入应用场景

文件写入在计算机中是一个非常常见的操作,下面的场景都用到了文件写入

  • 下载文件
  • 安装文件
  • 保存程序日志,如git
  • 编辑器保存文件
  • 视频录制

当需要持久化保存数据的时候,要想到文件写入

文件读取

顾名思义就是通过程序从文件中取出数据,有一下几种方法

复制代码
// 读取观书有感txt文件,并在控制台输出
const fs = require('fs')

// 1、异步读取
// fs.readFile('./观书有感.txt',(err, data)=>{
//     if(err){
//         console.log("读取失败")
//         return
//     }
//     console.log(data.toString()) //读取出来的数据是个buffer
// })

// 2、同步读取
// let data = fs.readFileSync("./观书有感.txt")
// console.log(data.toString())

// 3、流式读取

// const rs = fs.createReadStream("./haha.mp4");
// rs.on("data", chunk => {
//     console.log(chunk.length)  // 65536 => 64KB
// })

// // // 4、end 读取完成  可选事件
// rs.on("end", () => {
//     console.log("读取完成")
// })
应用场景
  • 电脑开机
  • 程序运行
  • 编辑器打开文件
  • 查看图片
  • 播放视频
  • git查看日志
  • 上传文件
  • 查看聊天记录

流式读取,一段一段的读取。

区别:

readFile: 一次读取所有所有内容。异步

readFileSync: 一次读取所有内容。同步

createReadStream: 分段读取

练习: 复制一个mp4文件。

复制代码
// 复制一个haha.mp4

const fs = require('fs')
const process = require('process')
// 步骤都是先读取,再写入

// 同步写入
// let data = fs.readFileSync("./haha.mp4")

// const ws = fs.writeFileSync("./haha1.mp4", data)
// console.log(process.memoryUsage()) // 43
// 流式操作
// 创建读取流对象
const rs = fs.createReadStream("./haha.mp4")
//创建写入流对象
const ws = fs.createWriteStream("./haha3.mp4")

rs.on('data', chunk => {
    // console.log(chunk)
    ws.write(chunk);
})

rs.on('end', ()=>{
    console.log(process.memoryUsage()) //35
})

// 快速写法
// rs.pipe(ws); //复制文件的意思


/**
 * 总结:
 * 第二种方式写入占用资源会少一些,第二种只占64KB,理想状态下。
 * 实际读取速度会快于写入速度。
 *  rss 整个占用内存的大小
 */

// 案例
// const process = require("process")  https://cloud.baidu.com/article/3285980
文件移动与重命名
javascript 复制代码
fs.rename(oldPath, newPath, callback)

fs.renameSync(oldPath, newPath)
复制代码
// 重命名观书有感txt
const fs = require('fs')

// 文件重命名
// fs.rename("./观书有感.txt", "./观书无感.txt", err => {
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log("操作成功")
// })

// 还可以用来做文件移动
fs.rename("./观书无感.txt", ".././观书无感.txt", err => {
    if(err){
        console.log("操作失败")
        return
    }

    console.log("操作成功")
})
// 同步同理
文件删除
复制代码
const fs = require('fs')

// 把观书无感删除

// 方法一 同步方法 unlinkSync
// fs.unlink("../观书无感.txt", err=>{
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log("操作成功")
// })

// 方法二 rm 方法 14.4  rmSync
// fs.rm("./观书有感.txt", err=>{
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log("操作成功")
// })
文件夹操作

创建文件夹:mkdir/mkdirSync

读取文件夹:readdir/readdirSync

删除文件夹: rmdir/rmdirSync

复制代码
const fs = require('fs')

// 创建一个文件夹
// fs.mkdir("./hello", err => {
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log("操作成功")
// });

// 递归创建 a/c/b recursive: true 递归创建
// fs.mkdir("./a/c/b", {recursive: true}, err => {
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log("操作成功")
// });

// 文件夹读取

// fs.readdir("./fs",(err, data)=>{
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log(data)
// })

// 删除文件夹
// fs.rmdir("./hello",err=>{
//     if(err){
//         console.log("操作失败")
//         return
//     }

//     console.log("操作成功")
// })
// 递归删除
// fs.rmdir("./a",err=>{
//     if(err){
//         console.log("操作失败", err)
//         return
//     }

//     console.log("操作成功")
// })

fs.rmdir("./a", {recursive: true}, err=>{
    if(err){
        console.log("操作失败", err)
        return
    }

    console.log("操作成功")
})
查看资源状态

使用stat或者statSync来查看资源的详细信息

复制代码
const fs = require("fs")

fs.stat("./fs/haha.mp4", (err, data)=>{
    if(err){
        console.log("操作失败")
        return
    }

    // console.log("操作成功", data)

    console.log("isFile", data.isFile())  //判断是否是一个文件

    console.log("isDirectory", data.isDirectory())  //判断是否是一个文件夹
})

fs练习,批量重命名

复制代码
const fs = require('fs');

fs.mkdirSync("./fs1") 

const files = fs.readdir("./fs", (err, data)=>{
    if(err){
        console.log("读取失败")
        return
    }

    // console.log(data)
    data.forEach((item,index)=>{
        console.log(item, index)
        let oldpath = "./fs/" + item

        let fileData = fs.readFileSync(oldpath)
        
        let rename = item.split(".")
        let newNma = rename[0] + 1 + "." + rename[1]

        fs.writeFileSync("./fs1/" + newNma, fileData)
    })
})
相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼9 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax