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的学习过程中,学习和总结的一些基础概念和文件系统模块方法的实践。其目的是在学时总结掌握,学后回顾复习,没有解决技术上的问题。