2021-02-09

本文介绍了Node.js的基础知识,包括CommonJS规范、Buffer的概念及应用,重点讲解了文件系统的多种操作方式,如同步与异步文件读写、简单文件读写、流式文件读写等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Node.js基础知识,文件系统总结

一、基础知识
1.CommonJS规范

ECMAScript标准的缺陷

  • 没有模块系统
  • 标准库较少
  • 没有标准接口
  • 缺乏管理系统

模块化

  • 如果程序设计的规模达到了一定的程度,则必须对其进行规模化。
  • 规模化有很多种形式,但至少应该提供能够将代码分割为多个源文件的机制
  • CommonJS的模块功能可以帮我们解决该解决的问题

CommonJS规范

  • CommonJS规范的提出,主要是为了弥补当前javascript没有模块化标准的缺陷

  • CommonJS规范为JS指定了一个美好的愿景。希望JS能够在任何地方运行

  • CommonJS对模块的引用十分简单:

    • 模块引用

      ​ 在规范中定义了require()方法,这个方法接收模块标识,以此将一个模块引入到当前运行环境中。

      // 引入其他的模块
      /*
        在node中,通过require()函数来引入外部的模块
          在require()可以传递一个文件的路径作为参数,node将     会自动根据该路劲来引入外部的模块
          这里路径,如果使用相对路径必须以. 或者 ..开头
        使用require()引入模块以后,该函数会返回一个对象,这个     对象代表的就是引入的模块
      
        我们使用require()引入外部模块是,使用的就是模块的标       识,我们可以通过标识来找到指定的模块
          模块分为两大类
            核心模块
              - 由node引擎提供的模块
              - 核心模块的表示就是模块的名字
            文件模块
              - 由用户自己创建的模块
              - 文件模块的标识就是文件的路径(绝对路径,相对路径)
                  相对路劲使用. 或 ..开头
      
      * */
      // 核心模块的引入
      var math = require("math")
      // 本地自定义模块的引入
      var md = require("./01.module");
      
    • 模块定义

      首先要理解node中模块的运行方式

      /*
          在node中有一个全局变量global,它的作用和网页中window类似
            在全局中创建的变量都会作为global的和属性保存
            在全局中创建的函数都会作为global的方法保存
            
            当node在执行模块中的代码时,他会首先在代码的最顶部,添加如下代码
              function (exports, require, module, __filename, __dirname) {
            在代码的最底部会添加如下代码:
                }
            实际上模块是包含在一个函数中执行的,并且再函数中同时传进
               exports
                  - 该对象用来将变量或函数暴露到外部
               require
                  - 函数用来引入外部的模块
               module
                  - 代表的是当前模块本身
                  - exports就是module的属性
                  - 既可以使用exports 导出,也可以使用module.exports导出
               __filename
                  D:\前端\2.服务器和工程化\Node.js\node\03.module.js
                  - 当前模块的完整路径
               __dirname
                  D:\前端\2.服务器和工程化\Node.js\node
                  当前文件模块所在文件夹的完整路径
      
      * */
      
      console.log(arguments.callee + "")
      

      其次我们才能了解模块究竟改如何定义

      /*
        exports 和 module.exports
            通过exports只能使用.的方式来向外部暴露背部变量
              export.xxx = xxx
            而module.exports既可以通过.的形式,也可以直接赋值
            module.exports.xxx = xxx
            module.exports = xxx
      * */
      // 创建一个对象
      exports = module.exports
      exports = {
        name : "张三",
        old : 18,
        gender : "男",
        sayName : function () {
          console.log(this.name)
        }
      }
      
      module.exports.name = "李四"
      module.exports.old = 18
      module.exports.gender = "女"
      module.exports.sayName = function () {
        console.log(this.name)
      }
      
    • 模块标识

      • 模块标识其实就是模块的名字,也就是传递给require()方法的参数,它必须是符合驼峰命名法的字符串,或者是以.、…开头的相对路径、或者绝对路径
      • 模块的定义十分简单,接口也十分简洁。每个模块具有独立的空间,它们互不干扰,在引用时也显得干净利落。
2.Buffer(缓冲区)

了解之前CommonJS的规范之后,我们便可以开始使用js来开发后台服务器了。

Buffer(缓冲区)是和数组类似的存储数据的容器,操作也和数组的操作有一些类似

唯一区别于数组的是数组不能存储二进制文件,而Buffer是专门来存储二进制文件的。

Buffer不需要引入模块,直接使用即可。

​ 其他关于Buffer的数据存储的方式以及一些Buffer的方法在代码注释中有,在这里就不赘述了。

/*在Buffer中存储的都是二进制文件,但是在显示的时候都是以十六进制显示的
      在Buffer中没一个元素的范围都是00-ff  0 - 255
      Buffer中的一个元素占一个字节
      Buffer的大小一旦确定,就不能修改,Buffer实际上是对底层内存的直接操作
*/

// 定义一个字符串
var str = "hello 张三"

// 将一个字符串保存到数组中
var buf = Buffer.from(str)

// Buffer中length属性是求占用内存的大小
console.log(buf.length)
// 字符串中的length属性是求字符串本身的长度
console.log(str.length)

console.log(buf)

// 创建一个10字节的Buffer
var buf1 = new Buffer(10)

// 通过数字下标索引来操作Buffer中的数据
buf1[0] = 88
buf1[1] = 0xcc
buf1[2] = 255
buf1[3] = 255

// 只要数字在控制台或者页面中显示就一定时以10进制的形式显示的
console.log(buf1)

// 在特定的需求下,需要以其他进制形式输出的时候,调用toString()方法此时toString()方法需要传一个参数
//这个参数就是需要以什么进制显示的进制数
console.log(buf1[2].toString(16))

// 使用Buffer.allocUnsafe()方法创建一个缓存区的时候,可能含有敏感数据
// 因为计算机为我们分配的内存中可能很有之前内存取残留的数据,
var buf3 = Buffer.allocUnsafe(10)
console.log(buf3)  //<Buffer 7c 69 00 00 33 09 00 00 38 32> 此时Buffer中是含有数据的,但是不是我们自己存储的

var buf4 = Buffer.from("我是一段字符串")

console.log(buf4)

/*
*  BUffer.form()  将一个字符串转化为BUffer
*  Buffer.allocUnsafe(size) 创建一个指定大小的Buffer,但是可能会含有敏感数字
*  Buffer.alloc(size) 创建一个指定大小的Buffer 这个方法是安全的
*  Buffer.toString()  将缓存区中的数据转换为字符串
*/

var buf5 = Buffer.alloc(10)
console.log(buf5)
二.文件系统

文件系统:简单来说就是通过Node来操作系统中的文件

使用文件系统,需要引入fs模块,fs是Node的核心模块,不需要下载,直接引入即可。

下面介绍一些文件系统常用的操作

1.同步文件的写入
/*
*   同步文件的写入:
*       - 手动操作的步骤
*         1.打开文件
*           fs.openSync(path[, flags, mode])
*              path 要打开文件的路径
*              flags 打开文件要操作的类型
*                 r 只读
*                 w 可写
*              mode 设置文件的权限,在window中一般不设置
* */

// 引入模块
var fs = require("fs")

// 打开文件
var fd = fs.openSync("hello.txt" , "w")

// 向文件内部写入需要写的内容
fs.writeFileSync(fd,"张三曾经是个王者")

// 保存并关闭文件、
fs.closeSync(fd)
2.异步文件的写入
// 首先引入模块
var fs = require("fs")

// 打开文件
fs.open("hello2.txt","w",function (err,fd) {
if(!err){
  console.log("打开文件成功")
}

// 写文件
  fs.write(fd,"后来他妈来了",function (err) {
    if(!err){
      console.log("文件写入成功")
    }
  })
  
//  关闭文件
  fs.close(fd,function (err) {
    if(!err){
      console.log("文件关闭成功")
    }
  })
})
3.简单文件写入
/*
    异步简单文件写入
    fs.writeFile(file, data[, options], callback)
      参数
        file - 文件的位置
        date 需要写进文件的数据
        options 选项,可以对写入进行一些设置
        callback 回调函数,当写入完成后执行的函数

        - flag
            r 只读
            w 之写
            a 追加
    同步简单文件写入
    fs.writeFileSync(file, data[, options])
      参数:
        file - 文件的描述,就是文件的路径
        data - 需要写进文件的数据
        option 选项,可以对写入有一些设置

*
* */

var fs = require("fs")

// 异步简单文件写入
fs.writeFile("C:\\Users\\38415\\Desktop\\hello.txt","张三曾经是个王者",{flag:"w"},function (err) {
  if(!err){
    console.log("文件写入成功")
  }else{
    console.log(err)
  }
})

//同步简单文件写入
fs.writeFileSync("C:\\Users\\38415\\Desktop\\hello.txt","后来他妈来了",{flag:"a"})
4.流式文件写入
/*
    同步、异步、简单的文件写入方式都不适合大文件的写入,性能较差,容易导致内存溢出

    流式文件写入
*   fs.createWriteStream(path[, options])
*     参数:
        path - 文件的路径
        option - 选项,可以对写入进行一些设置
* */

// 引入文件
var fs = require("fs")

// 创建一个可写流
var ws = fs.createWriteStream("hello.txt")
/*
* 可以通过监听流的open和close事件来监听流的打开和关闭
*
* on(事件字符串,回调函数)
*    - 可以为对象绑定一个属性
* once(事件字符串,回调函数)
*    - 可以为对象绑定一个一次性的时间,该事件将会在触发一次之后自动失效
* */
ws.once("open",function (){
  console.log("可写流打开了")
})

ws.write("张三曾经是个王者,")
ws.write("后来他妈来了,")
ws.write("从此一代王者就此陨落,")
ws.write("从此再无听闻,")

ws.once("close",function () {
  console.log("可写流关闭了")
})

ws.end()
5.同步文件读取
/*
*   同步文件读取
*   1.打开文件
*   fs.openSync(path[, flags, mode])
*   2.读取文件
*   fs.readSync(fd, buffer, [options])
*   3.关闭文件
*   fs.closeSync(fd)
* */
// 引入模块
var fs = require("fs")

// 定义一个Buffer来接收读取文件的内容
var buffer = new Buffer.alloc(1000);

var fd = fs.openSync("hello.txt","r")
fs.readSync(fd, buffer)
console.log(buffer.toString())
fs.closeSync(fd)
6.异步文件读取
/*
  异步文件读取
  1.打开文件
  fs.open(path[, flags[, mode]], callback)
  2.读取文件
  fs.read(fd, [options,] callback)
  3.关闭文件
    参数:
      fd 整数
      options 选项,可对文件读取进行设置
      callback 回调函数
* */



// 引入模块
var fs = require("fs")

fs.open("hello.txt","r",function (err,fd) {
  if(!err){
    console.log("文件打开成功")
  }
  
//  读取文件
  fs.read(fd,function (err,bytesRead,Buffer) {
    if(!err){
      console.log(Buffer.toString())
    }
  })

//  关闭文件
  fs.close(fd,function (err) {
    if(!err){
      console.log("文件关闭了")
    }
  })
})

7.简单文件读取
/*
  异步简单文件读取
* fs.readFile(path[, options], callback)
  同步简单文件读取
  fs.readFileSync(path[, options])
* */

// 引入模块
var fs = require("fs")

fs.readFile("hello.txt",function (err,data) {
  if(!err){
    fs.writeFile("hello02.txt",data,function (err) {
      if(!err){
        console.log("文件写入成功")
      }
    })
  }
})
8.流式文件读取
/*
  fs.createReadStream(path[, options])
* */

// 引入模块
var fs = require("fs")

// 创建读取流
var rs = fs.createReadStream("an.jpg")

// 创建写入流
var ws = fs.createWriteStream("newAn.jpg")

// 监听流
rs.once("open",function () {
  console.log("读取流打开了")
})

rs.once("close",function () {
  console.log("读取流关闭了")
  ws.end()
})

ws.once("open",function () {
  console.log("可写流打开了")
})

ws.once("close",function () {
  console.log("可写流关闭了")

})

rs.on("data",function (data) {
  ws.write(data)
})

使用pipe()方法重写流式文件读取

/*
*  流式文件读取也适用一些大的文件,可以风多次将文件读取到内存中
* */

var fs  = require("fs")

// 创建一个可读流
var rs = fs.createReadStream("a.mp3")

// 创建一个可写流
var ws = fs.createWriteStream("newA.mp3")

// pipe()可以将可读流中的内容,直接输出到可写流中
rs.pipe(ws)
9.文件系统的其他操作
// 引入模块
var fs = require("fs")

//验证路径是否存在
if(fs.existsSync("C:/Users/38415/Desktop/hello")){
  console.log("路径存在")
}

/*
获取文件信息
fs.stat(path[, options], callback)
fs.statSync(path[, options])
*/

fs.stat("C:/Users/38415/Desktop/hello/857.txt",function (err,stats) {
  if(!err){
    console.log(stats)
  }
})

console.log(fs.statSync("C:/Users/38415/Desktop/hello/857.txt"))


/*
删除文件
fs.unlink(path, callback)
fs.unlinkSync(path)
*/

fs.unlink("C:/Users/38415/Desktop/hello/857.txt" , function (err) {
  if(!err){
    console.log("文件已经被删除")
  }
})

if(!fs.unlinkSync("C:/Users/38415/Desktop/hello/857.txt")){
  console.log("文件被删除")
}

/*
列出文件
fs.readdir(path[, options], callback)
fs.readdirSync(path[, options])
*/
fs.readdir("C:/Users/38415/Desktop/hello",function (err,file) {
  if(!err){
    console.log(file)
  }
})
console.log(fs.readdirSync("C:/Users/38415/Desktop/hello"))

/*
截断文件
fs.truncate(path[, len], callback)
fs.truncateSync(path[, len])
*/
fs.truncate("C:/Users/38415/Desktop/hello/857.txt",10,function (err) {
  if(!err){
    console.log("文件截取成功")
  }
})

fs.truncateSync("C:/Users/38415/Desktop/hello/857.txt",10);

/*
建立目录
fs.mkdir(path[, options], callback)
fs.mkdirSync(path[, options])*/
fs.mkdir("C:/Users/38415/Desktop/hello02",{recursive:true},function (err,path) {
  if(!err){
    console.log(path)
  }
})

fs.mkdirSync("C:/Users/38415/Desktop/hello03")

/*
删除目录
fs.rmdir(path[, options], callback)
fs.rmdirSync(path[, options])
*/
fs.rmdir("C:/Users/38415/Desktop/hello03",function (err) {
  if(!err){

  }
})

fs.rmdirSync("C:/Users/38415/Desktop/hello02")

/*
重命名文件和目录
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)*/
fs.rename("C:/Users/38415/Desktop/hello01","C:/Users/38415/Desktop/hello00",function () {
  
})

fs.renameSync("C:/Users/38415/Desktop/hello00","C:/Users/38415/Desktop/hello05")

/*监视文件更改写入
fs.watchFile(filename[, options], listener)*/
fs.watchFile("C:/Users/38415/Desktop/hello/857.txt",{interval:1000},function (curr,prev) {
  console.log(prev.size)
  console.log(curr.size)
})

本身是初学者,以上是自己在刚接触Node.js的学习过程中,学习和总结的一些基础概念和文件系统模块方法的实践。其目的是在学时总结掌握,学后回顾复习,没有解决技术上的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值