Node.js-json-模块化-全局对象-fs-服务-Buffer

本文详细介绍了Node.js的基础知识,包括其介绍、作用、应用场景和相关命令。讲解了JSON、模块化的概念、引入与导出以及全局对象`global`的特点。深入探讨了文件系统`fs`的各种操作,如读取、写入、删除、移动文件等。最后,详细阐述了Buffer对象,包括创建、读写操作以及溢出、中文字符和单位换算的相关内容。

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

Node.js-json-模块化-全局对象-fs-服务-Buffer

1 node基础知识点

1.1介绍

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,是一个应用程序。

官方网址 https://nodejs.org/en/,中文站 http://nodejs.cn/

node:是一个运行JS的环境。

1.2 作用

  • 解析运行 JS 代码
  • 操作系统资源,如内存、硬盘、网络

1.3 应用场景

  • APP 接口服务 一个接口就是一个地址
  • 网页聊天室。
  • 动态网站, 个人博客, 论坛, 商城等
  • 后端的Web服务,例如服务器端的请求(爬虫),代理请求(跨域)
  • 前端项目打包(webpack, gulp)

1.4 相关命令


1 打开 win+r cmd 或者地址输入 cmd回车
2 查看node版本:  node -v 
  进入node环境: node 回车
  退出环境:     ctr+c
  自动查找文件:  tab
3 运行JS文件     node 01-my.js:运行当前目录下的 01-my.js
4 清屏:cls
5 显示当前的文件列表 dir
6 切换盘符: c:
7 进入到上级目录:   cd..
  进入到one文件夹:  cd one
注意

在 nodejs 环境下,不能使用 BOM 和 DOM ,也没有全局对象 window,全局对象的名字叫 global

2 json

javascript object notation:对象表示方法,对象标记,数据交换格式

json:javascript object notation js对象的表达方式

json作用:实现前后端之间的通讯所传递的一种数据格式,类似于对象

与对象相同点:json与对象都是有键值对。{} 【】

与对象不同点:

① json属性必须加上双引号

② json最后一个属性结束时,不要加逗号

③ json的属性值不能是函数,NaN,undefined

④ json是前后端通讯时的数据之一,对象是通过类实例化出来的。

[
    {
        "useName":"xixi",
        "age":123
       
    }
]

对象与json是可以相互转换的,创建后缀为.js的文件

const obj = {
    a:1,
    b:2
}

stringifg:将对象转换为json字符串

const str = JSON.stringify(obj);
console.log(str); //{"a":1,"b":2}

parse:json字符串转换为json对象

const obj2 = JSON.parse(str);
console.log(obj2)  //{ a: 1, b: 2 }

3 模块化

3.1 模块化介绍

模块化指的就是将一个大的功能拆分为一个一个小的模块,通过不同的模块的组合来实现一个大功能。

  1. 在node中一个 js 文件就是一个模块
  2. 模块内部代码对于外部来说都是不可见的,可以通过两种方式向外部暴露

模块有:内置模块、自定义模块、第三方模块

3.2 引入与导出

模块内对外暴露数据注意以下几点:

1)模块内如果没有暴露数据,引人模块的时候会得到一个空对象。

2)module.exports 可以暴露任意数据。

创建并暴露模块,新建mo.js

const a = 12;
module.exports = a;

导出模块,新建index.js,并在

//mo1.js当中的 module.exports是什么那么mo1就是什么!!
const mo1 = require("./module/mo1.js")
console.log(mo1);//把a的值赋值给mo1   值为12

3.3 引入模块特点

① mo1.js当中的 module.exports是什么那么mo1就是什么

② 后缀.js是可以省略的

注意:node_modules一般存放的是第三方的模块,自定义的模块一般不会放置到该文件夹中,文件名必须叫node_modules。

③ 当js文件不在node_modules文件夹下,是不允许省略前缀的。若没有在当前文件夹找到,则会自动向上上级目录中的 node_modules 查找,一直到根目录。

const mo1 = require("module/mo1");// Cannot find module 'module/mo1'

创建node_modules文件夹,在此文件夹下创建文件mo1.js

const mo1 = require("mo1")
console.log(mo1)  //12

④ 当省略.js 会有两种含义:

i 会使用当前文件.js (第一种情况优先被选择)

ii 是一个json文件

iii 会使用当前文件下的index.js

index.js是可以省略不写的。当你只指定文件夹时,默认引入index.js

创建mo2文件夹,在mo2下创建index.js文件,暴露此文件

module.exports = "module->mo->index.js"

引入文件

const mo2 = require("./module/mo2/index")
console.log(mo2)  //module->mo->index.js

const mo2 = require("./module/mo2")
console.log(mo2)  //module->mo->index.js

⑤ 如果要更改默认值index,将默认值 index.js 指定为 home.js,在package.json中写入home.js

新建mo3文件夹,在文件夹中创建index.js ,home,js , package.json

暴露的文件分别为

module.exports = "module->mo3->index.js"
module.exports = "module->mo3->home.js";
{
  "main": "home.js"
}

则引入的文件则更改了默认值

const mo3 = require("./module/mo3")
console.log(mo3)  //module->mo3->home.js

⑤ 导入的是对象

const d = 4;
const e = 5;
const f = 6;
module.exports = {
    a:1,
    b:2,
    c:3,
    d,
    e,
    f,
    run(){
        console.log("run执行啦",this.a,this.b,this.c)
    }
}
const mo4 = require("./module/mo4");
console.log(mo4); //{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, run: [Function: run] }
mo4.run();  //run执行啦 1 2 3

// 使用对象解构赋值
const {a,b,run} = require("./module/mo4");
console.log(a,b);//1 2
run(); //run执行啦 undefined

⑥ 如果直接给module.exports增加属性

module.exports.a = 1;
module.exports.b = 2;
module.exports.c = 3;
module.exports.d = 4;
module.exports.e = 5;
module.exports.run = function () {
    console.log(this);
}
const mo5 = require("./module/mo5");
console.log(mo5);
mo5.run();  //{ a: 1, b: 2, c: 3, d: 4, e: 5, run: [Function] }

⑦ 模块化当中,导出时,最终导出的是module.exports。而exports只是module.exports的引用地址相同。

module.exports.a = 1;
module.exports.b = 2;
console.log(module.exports === exports);// true

如果导出对象使用module.exports, 其它 类型可以使用exports。 exports 不要直接导出对象

 module.exports = {
     c:1000
 }
 exports = {
     c:999   
 }
console.log(module.exports === exports);// false

⑧ 模块化之间是可以相互依赖

const mo6 = require("../mo6");
exports.str = "mo7->index.js";
exports.a = mo6.a;
const mo7 = require("./module/mo7");
console.log(mo7);  //{ str: 'mo7->index.js', a: 1 }

⑨ 可以直接引入json文件

新建文件my.js

exports.str = "json->my.js"
const my = require(".//my.js");// js --> json -->文件夹
console.log(my);// 会将JSON-->JSON对象

4 全局对象 global object

4.1 node 中没有window

node中没有window,document,不支持

4.2 全局对象

node当中每一个JS就是一个模块,每一个模块都有自己的作用域,在该模块当中通过var定义的变量,不会存储在全局对象中(相当于在函数当中定义了变量,这个变量也不会指向window)

global 他是在模块之上的

var a = 1;
console.log(global.a);// undefined

a = 1;
console.log(global.a)

在函数内定义变量a=100,可以输出全局

//暴露
var a = 1;
b = 10000;
console.log(a);
a = 100;
const mo = require("./mo");
console.log(global.b);  //10000
console.log(global.a);  //1

5 _ ___dirname与____filename

5.1 _dirname

当前js所在的完整目录,结果与node执行时的环境无关。

console.log(__dirname);//完整路径

_dirname并不是全局对象下的属性,而是内置的属性

console.log(global.__dirname);// undefined

5.2 _filename

文件完整的地址,包含文件名字。

console.log(__filename);//本身的名字

_filename是一个绝对地址 ./ …/ …/…/ /

6 fs文件系统

fs 全称为 file system,是 NodeJS 中的内置模块,可以对计算机中的文件进行增删改查等操作。

6.1 读取文件

readFile:第一个参数是读取文件的地址,第二个参数是一个回调函数,读取文件是异步行为。回调函数的第一个参数是错误信息err,第二个参数是读取以后的结果result

第一个参数文件的地址是相对地址,此相对地址相对的不是代码所在的文件,而是相对的node执行环境地址。所以加上_dirname与地址进行拼接。

而模块的地址则是当前代码所在的文件地址,不是node 运行环境地址

新建one.txt文件

const fs = require("fs");
// 第一个参数是读取文件的地址,第二个参数是一个回调函数。读取文件是异步行为。
fs.readFile(__dirname+"/one.txt",function(err,result) {
    // console.log(err)  //null 表示没有问题
    if(err) {
        console.log("读取失败",err)//null的布尔值是false
    } else {
        console.log("领取成功",result.toString())  //领取成功 11111
        //不加toString() 输出<Buffer 31 31 31 31 31 0a>
         Buffer:是缓冲区。数据还没有自己的格式const fn = require("fs")
    }
})
6.1.1 简单读取
  • fs.readFile(file, function(err, data){})
  • fs.readFileSync(file) 返回值就是读取的内容,写入的返回为undefined
const fs = require("fs");
const result = fs.readFileSync(__dirname+"/my.txt"); //result就是返回的结果
console.log(result.toString());// abc
6.1.2 流式读取
  • fs.createReadStream(); 和流式写入结合使用

    两个参数,一个参数为data,end,和回调函数

    thunk:数据块 把大的数据分成若干份,分批读取,每次读取64k

const fs = require("fs");
const rs = fs.createReadStream(__dirname+"/123.mp4");

let str = "";
// 将数据分成若干个数据块。
rs.on("data",function (thunk) { // 64k
    // console.log("data");
    str+=thunk;
    console.log(thunk.length);
});
// 读取完毕
rs.on("end",function () {
    // console.log("end");
    // console.log(str);
})
6.1.3 练习:复制文件
const fs = require("fs");
// 非流式
// fs.readFile(__dirname+"/123.mp4",function (err,result) {
//     fs.writeFile(__dirname+"/one.mp4",result,function (err) {
//         console.log("成功",err)
//     })
// })

// 流式
// 读取流
const rs = fs.createReadStream(__dirname+"/123.mp4");
// 写入流
const ws = fs.createWriteStream(__dirname+"/three.mp4");

// 1
// rs.on("data",function (thunk) {
//     ws.write(thunk);
// })
// 简写
rs.pipe(ws);// gulp webpack 管道

6.2 写入文件

writeFile:

第一个参数是写入的文件地址

第二个参数是要写入的内容

第三个参数可以省略,默认**{flag:“w”},可以追加内容{flag:“a”}** ,换行\n

第四个参数是回调函数,当文件写入成功后执行

const fs = require("fs");
fs.writeFile(_dirname+"/one.txt","22222\n",{flag:"a"},function(err) {
    console.log("写入成功")
})
6.2.1 简单写入
  • fs.writeFile(file, data, [,options], callback);
  • fs.writeFileSync(file, data);
  • options 选项
    • encoding 默认值: `‘utf8’
    • flag 默认值: 'w'
简单写入特点

① 在当前文件中,如果没有指定文件,那么会创建。然后再写入。

const fs = require("fs")
fs.writeFile(__dirname+"/my.txt","1234",function(err) {
    console.log(err) //null 成功写入,自动创建的my文件里就有有1234
})

② 写入时,如果没有文件夹会报异常

③ 设置{flag:“a”}// a:追加 默认是w

④ 设置 encoding 编码格式 ,默认utf-8

fs.writeFile(__dirname+"/my.txt","两岸猿声蹄不住",{flag:"a",encoding:"utf-8"},function (err) {
    // err 为 null说明写入成功
    console.log(err);
})

⑤ 写入是异步的

fs.writeFile(__dirname+"/my.txt","两岸猿声蹄不住",{flag:"a",encoding:"utf-8"},function (err) {
    // err 为 null说明写入成功
    console.log(err);
})
console.log("你还好吗?")  //先输出你还好吗,再输出null

⑥ 可以同步写入,同步有可能会造成阻塞。

fs.readFile(__dirname+"/123.mp4",function (err,result) {
    let t = Date.now();
     // 同步
    fs.writeFileSync(__dirname+"/my.txt",result);
    console.log(Date.now()-t); //0
})
6.2.2 流式写入:文件比较大
  • fs.createWriteStream(path[, options])
    • path
    • options
      • flags 默认值: 'w'
      • encoding默认值: `‘utf8’
    • 事件监听 open close eg: ws.on(‘open’, function(){});
// 数据流。 当数据比较大时,建议使用流式写入。
const fs = require("fs");
const ws = fs.createWriteStream(__dirname+"/my.txt");
ws.on("open",function () {
    console.log("打开数据流");
})
ws.write("a");
ws.on("close",function () {
    console.log("关闭数据流")
})
ws.write("b"); //写要放到close的上面
ws.write("c")
ws.close();// 关闭数据流

6.3 文件删除:unlink

  • fs.unlink(’./test.log’, function(err){}); 异步删除

第一个参数是删除文件的目录,第二个参数是一个回调,用于得到删除之后的结果

fs.unlink(__dirname+"/my1.txt",function (err) {
    console.log(err);
})
  • fs.unlinkSync(’./move.txt’); 同步删除
fs.unlinkSync(__dirname+"/123.mp4");

6.4 移动文件 + 重命名:rename

  • fs.rename(’./1.log’, ‘2.log’, function(err){})

重命名:第一个参数是操作的文件目录,第二个参数是操作的结果

移动:要保证相对应的文件夹是存在的

fs.rename(__dirname+"/one.mp4",__dirname+"/oneone.mp4",function (err) {
    console.log(err);
})
移动:要保证相对应的文件夹是存在的,新建a文件夹
fs.rename(__dirname+"/oneone.mp4",__dirname+"/a/a.mp4",function (err) {
    console.log(err);
})
  • fs.renameSync(‘1.log’,‘2.log’)
同步
fs.renameSync(__dirname+"/a/b/c/a.mp4",__dirname+"/one.mp4");

6.5 文件夹操作

  • mkdir 创建文件夹

    第一个参数为目录的地址,一般只能创建一个目录,可使用{recursive:true}递归创建多个文件夹

    • path
    • options
      • recursive 是否递归调用
    • callback
fs.mkdir(__dirname+"/b/c/d",{recursive:true},function (err) {
     console.log(err);
 })
  • rmdir 删除文件夹 文件夹必须是空的 如果是要有内容,可使用{recursive:true}递归
 fs.rmdir(__dirname+"/b",{recursive:true},function (err) {
     console.log(err);
 })
  • readdir 读取文件夹 目录列表
fs.readdir(__dirname,function (err,result) {
    console.log(err,result); })

6.6 判断文件或目录是否存在:exists

· exists

· existsSync 同步

fs.exists(__dirname+"/twi.mp4",function (isHas) {
    console.log(isHas)
})

同步判断 · isHas

 const isHas = fs.existsSync(__dirname+"/two2.mp4");
 console.log(isHas);// false

6.7判断是文件还是文件夹(目录):stat

· stat:

①可输出两个参数,state,isFile() 这是一个布尔值,如果地址是一个文件,就是true

fs.stat(__dirname+"/one.mp4",function (err,state) {
    // console.log(err,state);
    console.log(state.isFile());// true 是一个布尔值,如果地址是一个文件,那么结果 为true
})

② 如果地址是一个目录,用参数state,isDirectory ,值为布尔值,是的话就为true

fs.stat(__dirname+"/a",function (err,state) {
    // console.log(state.isFile());// false
    console.log(state.isDirectory());// true  文件是在一个文件夹中
})

7 url

是内置模块,直接引入即可

const url = require("url")
const str = "http://lisi:123456@www.zhangsan.com:8090/a/b/c?userName=zhangsan&age=12#abcdefg"
const result = url.parse(str)  //解析地址
// console.log(result)
// 常用
console.log(result.pathname);  //站点资源目录 /a/b/c
console.log(result.query)      //userName=zhangsan&age=12

// Url {
//     protocol: 'http:',             协议
//     slashes: true,                 包含斜线值为true,否则为false
//     auth: null,                    访问权限,可设置密码 lisi:123456
//     host: 'www.zhangsan.com:8090', 域名+端口号
//     port: '8090',                  端口号
//     hostname: 'www.zhangsan.com',  域名
//     hash: '#abcdefg',              片段
//     search: '?userName=zhangsan&age=12',      带?的查询
//     query: 'userName=zhangsan&age=12',        不带?的查询
//     pathname: '/a/b/c',                       站点资源目录 url
//     path: '/a/b/c?userName=zhangsan&age=12',  资源目录+查询
//     href: 'http://www.zhangsan.com:8090/a/b/c?userName=zhangsan&age=12#abcdefg' 完整地址
//   }

将字符串转为对象,用split分割遍历。或者直接parse(str,true)

有true就是对象格式,没有true,是字符串格式

console.log(url.parse(str,true).query)   
//[Object: null prototype] { userName: 'zhangsan', age: '12' }

// 原来的方法
const path = "userName=zhangsan&age=12";
const arr = path.split("&");
const obj = {};
arr.forEach(item=>{
    const [key,value] = item.split("=");// [userName,zhangsan]
    obj[key] = value
})
console.log(obj);

简单的例子

const url = require("url");
const str = "/a/b/c?a=1&b=2";
console.log(url.parse(str).pathname);// /a/b/c
console.log(url.parse(str,true).query);// { a: '1', b: '2' }

http默认端口号80

https默认端口号443

输出出现两次,浏览器请求了两次,第一次网址,第二次站标

8 创建服务

createServer:是一个函数,通过该函数可以创建你的站点服务

request:请求对象,所有与请求相关的信息,简写req

response:响应对象,与响应相关的信息,简写res

listen是一个函数,接收三个参数:

① 第一个参数是端口号(必写)

② 第二个参数是指定IP,可以不写,本机默认的IP

③ 第三个参数是指定回调函数,该回调函数会在服务创建成功后执行

注意:

① 代码修改之后,一定一定要重新启动服务

② 服务是可以开启多个的,但是端口号不允许重复(listen EADDRINUSE: address already in use 127.0.0.1:8090: 说明端口号被占用)

③ server.js中的代码不是在浏览器中运行的,而是在NODE环境中执行的

④ node 是没有文件夹容器概念

const http = require("http");
const server = http.createServer(function(req,res) {
    console.log(1)
    res.end ("成功显示")
})
server.listen(8091,"127.0.0.1",function() {
    console.log("success")
})

在地址栏中请求数据,叫get

res.end只支持字符串和buffer

9 Buffer

数据流:指的是对文件进行读写时产生的。A---->B. fs.readFile 流式读取,流式写入

Buffer:fs.readFile()-------->abcdefg <Buffer ox ox

const fs = require("fs")
fs.readFile = (_dirname+"/my/txt",function(err,result) {
    //将内容以十六进制的形式进行展现,存储的还是二进制
	console.log(result)
})
//针对JS而言,字符是数字表示,计算器会将这些数字转换成二进制
const str = "b";
console.log(str.charCodeAt()) //98 unicode

9.1 Bufferr 介绍

Buffer 是一个和数组类似的对象,不同是 Buffer 是专门用来保存二进制数据的。

特点:

  • 大小固定:在创建时就确定了,且无法调整
  • 性能较好:直接对计算机的内存进行操作
  • 每个元素大小为 1 字节(byte)

9.2 操作

9.2.1 创建 Buffer
  • 直接创建 Buffer.alloc() 指定两个参数,第一个参数为字节的个数,第二个参数为初始值

    const b1 = Buffer.alloc(5,10)
    console.log(b1)  //<Buffer 0a 0a 0a 0a 0a>
    
  • 不安全创建 Buffer.allocUnsafe()

与alloc的区别:allocUnsafe()没有初始值,会使用上一应用程序的遗留数据。速度快

const b3 = Buffer.allocUnsafe(5);
console.log(b3); //<Buffer 3d 00 20 00 31>
  • 通过数组和字符串创建 Buffer.from() 只允许写入字符和数组

得到对应的十六进制

const b4 =Buffer.from("45");// <Buffer 34 35>
console.log(b4) //与图对应,十六进制

数组中写字符得到的都是0

const b7 = Buffer.from(["a","b","*"]);// 字符全部都是0.
console.log(b7);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KKElzJh2-1621071679909)(C:\Users\王秀\AppData\Roaming\Typora\typora-user-images\image-20210511183528278.png)]

9.2 Buffer 读取和写入

可以直接通过 [] 的方式对数据进行处理,可以使用 toString 方法将 Buffer 输出为字符串

  • [ ] 对 buffer 进行读取和设置
  • toString 将 Buffer 转化为字符串
const b1 = Buffer.from("iloveyou");
console.log(b1);// <Buffer 69 6c 6f 76 65 79 6f 75>十六进制
console.log(b1[0]);// 105 十进制
console.log(b1[1]);//108
b1[0]= 35;
console.log(b1.toString());// buffer转为字符串 #loveyou
9.3 关于溢出

溢出的高位数据会舍弃 保留后位

const b1 = Buffer.alloc(5,256);//十进制转为十六进制为100 ,取后面两位
console.log(b1);  //<Buffer 00 00 00 00 00> 
9.4 关于中文

一个 UTF-8 的中文字符大多数情况都是占 3 个字节

const b1 = Buffer.from("中国");
console.log(b1); //<Buffer e4 b8 ad e5 9b bd>
9.5 关于单位换算

1Bit 对应的是 1 个二进制位

1 字节 = 8 Bit(byte) 11111111=>255

十进制转二进制 12 除2倒取余=1100

二进制 1100 转十进制 1×2的3次方+1×2的2次方

1024Byte = 1KB

1024KB = 1MB

1024MB = 1GB

1024GB = 1TB

-KKElzJh2-1621071679909)]

9.2 Buffer 读取和写入

可以直接通过 [] 的方式对数据进行处理,可以使用 toString 方法将 Buffer 输出为字符串

  • [ ] 对 buffer 进行读取和设置
  • toString 将 Buffer 转化为字符串
const b1 = Buffer.from("iloveyou");
console.log(b1);// <Buffer 69 6c 6f 76 65 79 6f 75>十六进制
console.log(b1[0]);// 105 十进制
console.log(b1[1]);//108
b1[0]= 35;
console.log(b1.toString());// buffer转为字符串 #loveyou
9.3 关于溢出

溢出的高位数据会舍弃 保留后位

const b1 = Buffer.alloc(5,256);//十进制转为十六进制为100 ,取后面两位
console.log(b1);  //<Buffer 00 00 00 00 00> 
9.4 关于中文

一个 UTF-8 的中文字符大多数情况都是占 3 个字节

const b1 = Buffer.from("中国");
console.log(b1); //<Buffer e4 b8 ad e5 9b bd>
9.5 关于单位换算

1Bit 对应的是 1 个二进制位

1 字节 = 8 Bit(byte) 11111111=>255

十进制转二进制 12 除2倒取余=1100

二进制 1100 转十进制 1×2的3次方+1×2的2次方

1024Byte = 1KB

1024KB = 1MB

1024MB = 1GB

1024GB = 1TB

平时所说的网速 10M 20M 100M 这里指的是 Bit ,所以理论下载速度 除以 8 才是正常的理解的下载速度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值