Node.js 入门学习笔记

知识储备

1.命令行窗口

   目录
		. 表示当前目录
		.. 表示上一级目录
	
   常用的指令:
		dir 列出当前目录下的所有文件
		cd 目录名 进入到指定的目录
		md 目录名 创建一个文件夹
		rd 目录名 删除一个文件夹	
	
   环境变量(windows系统中变量)	
   path
		C:\work\jdk\jdk1.7.0_75/bin;
		。。。。
		C:\Users\zl\Desktop\hello
		
	      当我们在命令行窗口打开一个文件,或调用一个程序时,
	系统会首先在当前目录下寻找文件程序,如果找到了则直接打开
	如果没有找到则会依次到环境变量path的路径中寻找,直到找到
	为止如果没找到则报错所以我们可以将一些经常需要访问的程序
	和文件的路径添加到path中,这样我们就可以在任意位置来访问
	这些文件和程序了

2、I/O (Input/Output),I/O操作指的是对磁盘的读写操作

Node是什么

1、node是一款对ES标准实现的JS引擎
2、通过node可以使js在服务器中运行
3、node就是一款使用js编写的web服务器
4、node底层是使用c++的编写的
5、node的中js引擎使用的chrome的v8引擎
6、node的特点:
                      a.非阻塞、异步的I/O
                      b.事件和回调函数
                      c.单线程(主线程单线程,后台I/O线程池)
                      d.跨平台

模块化

1、ES5中没有原生支持模块化,我们只能通过script标签引入js文件来实现模块化,ES6内置了模块化,定义暴露模块 : export

2、在node中为了对模块管理,引入了CommonJS规范

3、模块的引用

		使用 require()函数来引入一个模块
	    如:var 变量 = require("模块的标识");

4、模块的标识

       模块的标识就是模块的名字或路径,我们node通过模块的标识来寻找模块的
	   对于核心模块(npm中下载的模块),直接使用模块的名字

5、模块的定义

     在node中一个js文件就是一个模块, 默认情况下在js文件中编写的内容,都是运行在一个独立的函数中,外部的模块无法访问,但是我们可以导出变量和函数。
   
     导出变量和函数
     1、使用 exports 
     例子:
			exports.属性 = 属性值;
			exports.方法 = 函数;
							
     2、使用module.exports
     例子:
		    module.exports.属性 = 属性值;
			module.exports.方法 = 函数;
			module.exports = {};
			
     对其进行引入
			var fs = require("xx");
			var express = require("xx");
		


				
     对于自定义的文件模块,需要通过文件的路径来对模块进行引入,路径可以是绝对路径,如果是相对路径必须以./或 ../开头
	    	var router = require("./router");
]
	在node中,通过require()函数来引入外部的模块
		require()可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块
		这里路径,如果使用相对路径,必须以.或..开头

	使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块
	我们使用require()引入外部模块时,使用的就是模块标识,我们可以通过模块标识来找到指定的模块
    模块分成两大类
		核心模块
			- 由node引擎提供的模块
			- 核心模块的标识就是,模块的名字
		文件模块
			- 由用户自己创建的模块
			- 文件模块的标识就是文件的路径(绝对路径,相对路径)
				相对路径使用.或..开头






	在node中有一个全局对象 global,它的作用和网页中window类似
		在全局中创建的变量都会作为global的属性保存
		在全局中创建的函数都会作为global的方法保存
		

	当node在执行模块中的代码时,它会首先在代码的最顶部,添加如下代码
 			function (exports, require, module, __filename, __dirname) {
                   在代码的最底部,添加如下代码
 			}

 	实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了5个实参
		 exports
		 	- 该对象用来将变量或函数暴露到外部
		 	 
		 require
		 	- 函数,用来引入外部的模块

		 module
		 	- module代表的是当前模块本身
		 	- exports就是module的属性
		 	- 既可以使用 exports 导出,也可以使用module.exports导出
		 	 
		 __filename
 			C:\Users\zl\WebstormProjects\class0705\01.node\04.module.js
 			- 当前模块的完整路径

	  	 __dirname
 			C:\Users\zl\WebstormProjects\class0705\01.node
 			- 当前模块所在文件夹的完整路径



   	exports 和 module.exports
		- 通过exports只能使用.的方式来向外暴露内部变量
			exports.xxx = xxx

		- 而module.exports既可以通过.的形式,也可以直接赋值
			module.exports.xxx = xxxx
			module.exports = {}

npm的命令

通过npm下载的包都放到node_modules文件夹中,我们通过npm下载的包,直接通过包名引入即可。node在使用模块名字来引入模块时,它会首先在当前目录的node_modules中寻找是否含有该模块
1、如果有则直接使用,如果没有则去上一级目录的node_modules中寻找
2、如果有则直接使用,如果没有则再去上一级目录寻找,直到找到为止
3、直到找到磁盘的根目录,如果依然没有,则报错

	 npm -v 查看npm的版本
	 npm version 查看所有模块的版本
	 npm search 包名 搜索包
	 npm install / i 包名 安装包
	 npm remove / r 包名 删除包
	 npm install 包名 --save 安装包并添加到依赖中
	 npm install 下载当前项目所依赖的包
	 npm install 包名 -g 全局安装包(全局安装的包一般都是一些工具)

包(package)

将多个模块组合为一个完整的功能,就是一个包
包结构
	bin:
		 二进制的可执行文件,一般都是一些工具包中才有
	lib:
		 js文件
	doc:
		 文档
	test:
		 测试代码
	package.json:
		 包的描述文件
		
    package.json:
	    它是一个json格式的文件,在它里面保存了包各种相关的信息
		     name 包名
		     version 版本
	     	 dependencies 依赖
	    	 main 包的主要的文件
		     bin 可执行文件

文件系统(File System)

1、Buffer(缓冲区)
Buffer和数组的结构的非常类似,Buffer是用来存储二进制数据的

 Buffer的方法:
	 Buffer.from(字符串):将一个字符串中内容保存到一个buffer中
	  
     buf.toString(): 将buffer转换为一个字符串
     
     Buffer.alloc(size):创建一个指定大小的buffer对象
     
     Buffer.allocUnsafe(size):创建一个指定大小的buffer对象,可以包含敏感数据(未将创建的内存区域的清空)

更多内容:Node官网 方法

2、fs模块
在Node通过fs模块来对系统中的文件进行操作,fs模块是node中已经继承好了,不需要在使用npm下载,直接引入即可

1、引入fs
	  var fs = require("fs");
			
2、fs模块中的大部分操作都提供了两种方法,同步方法和异步方法
       同步方法带sync
	   异步方法没有sync,都需要回调函数

		
3、方法( 带sync的都是同行的方法,有callback回调函数的都是异步方法)
   打开文件
      fs.open(path, flags[, mode], callback)
      fs.openSync(path, flags[, mode])
   关闭文件
      fs.close(fd, callback)
      fs.closeSync(fd)


   写入文件
   
	    1.同步写入
	       fs.writeSync(fd, buffer, offset, length[, position])
           fs.writeSync(fd, data[, position[, encoding]])
           要完成同步写入文件,先需要通过openSync()打开文件来获取一个文件描述符,然后在通过writeSync()写入文件。
           参数: – fd 文件描述符,通过openSync()获取
                 – data 要写入的数据(String 或 Buffer)
                 – offset buffer写入的偏移量
                 – length 写入的长度
                 – position 写入的起始位置
                 – encoding 写入编码
                 
		2.异步写入
          fs.write(fd, buffer, offset, length[, position], callback)
          fs.write(fd, data[, position[, encoding]], callback)
          要使用异步写入文件,先需要通过open()打开文件,然后在回调函数中通过write()写入。
          参数: – fd 文件描述符
				– data 要写入的数据(String 或 Buffer)
				– offset buffer写入的偏移量
				– length 写入的长度
				– position 写入的起始位置
				– encoding 写入编码
					
		3.简单写入
			fs.writeFile(file, data[, options], callback)
		    fs.writeFileSync(file, data[, options])
		    参数:  – file 文件路径
	               – data 被写入的内容,可以是String或Buffer
	               – options 对象,包含属性(encoding、mode、flag)
	               – callback 回调
		               
		4.流式写入
		往一个文件中写入大量数据时,最好的方法之一是使用流。
        若要将数据异步传送到文件,首需要使用以下语法创建一个Writable对象:
        fs.createWriteStream(path[, options])
              -path 文件路径
              -options {encoding:"",mode:"",flag:""}
        一旦你打开了Writable文件流,就可以使用
        write()方法来写入它,写入完成后,再调用end()方法来关闭流



 读取文件
		1.同步读取
		   fs.readSync(fd, buffer, offset, length, position)
           参数:
				-fd 文件描述符
				-buffer 读取文件的缓冲区
				-offset buffer的开始写入的位置
				-length 要读取的字节数
				-position 开始读取文件的位置
				
			
		2.异步读取
		   fs.read(fd, buffer, offset, length, position, callback)
	       参数:
				-fd 文件描述符
				-buffer 读取文件的缓冲区
				-offset buffer的开始写入的位置
				-length 要读取的字节数
				-position 开始读取文件的位置
				-callback 回调函数 参数err , bytesRead , buffer


		3.简单读取
           fs.readFile(file[, options], callback)
           fs.readFileSync(file[, options])
		   参数:    -file 文件路径或文件描述符
		           -options <Object> | <String>
		           -encoding <String> | <Null> 默认 = null
		           -flag <String> 默认 = 'r'
		           -callback 回调函数,有两个参数err 、data


		4.流式读取
           从一个文件中读取大量的数据时,最好的方法之一就是流式读取,这样将把一个文件作为Readable流的形式打开。要从异步从文件传输数据,首先需要通过以下语法创建一个Readable流对象:
           fs.createReadStream(path[, options])
           -path 文件路径
           -options {encoding:"",mode:"",flag:""}
           
           当你打开Readable文件流以后,可以通过readable事件和read()请求,或通过data事件处理程序轻松地从它读出。


其他方法:
        验证路径是否存在
        – fs.existsSync(path)
        
        获取文件信息
		– fs.stat(path, callback)
		– fs.statSync(path)
		
		删除文件
		– fs.unlink(path, callback)
		– fs.unlinkSync(path)
		
		列出文件
		– fs.readdir(path[, options], callback)
		– fs.readdirSync(path[, options])
		
		截断文件
		– fs.truncate(path, len, callback)
		– fs.truncateSync(path, len)
		
		建立目录
		– fs.mkdir(path[, mode], callback)
		– fs.mkdirSync(path[, mode])
		
		删除目录
		– fs.rmdir(path, callback)
		– fs.rmdirSync(path)
		
		重命名文件和目录
		– fs.rename(oldPath, newPath, callback)
		– fs.renameSync(oldPath, newPath)
		
		监视文件更改写入
		– fs.watchFile(filename[, options], listener)
					

在这里插入图片描述

更多官方方法:Node官网 方法

代码:

1、Buffer(缓冲区)

	- Buffer的结构和数组很像,操作的方法也和数组类似
	- 数组中不能存储二进制的文件,而buffer就是专门用来存储二进制数据
	- 使用buffer不需要引入模块,直接使用即可
	- 在buffer中存储的都是二进制数据,但是在显示时都是以16进制的形式显示
	buffer中每一个元素的范围是从00 - ff   0 - 255
	00000000 - 11111111

	计算机 一个0 或一个1 我们称为1位(bit)

	8bit = 1byte(字节)
	1024byte = 1kb
	1024kb = 1mb
	1024mb = 1gb
	1024gb = 1tb

	buffer中的一个元素,占用内存的一个字节
   	Buffer的大小一旦确定,则不能修改,Buffer实际上是对底层内存的直接操作

	var str = "Hello 尚硅谷";
	
	//将一个字符串保存到buffer中
	var buf = Buffer.from(str);
	
	//console.log(buf.length); //占用内存的大小
	//console.log(str.length);//字符串的长度
	//console.log(buf);
	
	//创建一个指定大小的buffer
	//buffer构造函数都是不推荐使用的
	//var buf2 = new Buffer(10);//10个字节的buffer
	//console.log(buf2.length);

	//创建一个10个字节的buffer
	var buf2 = Buffer.alloc(10);
	//通过索引,来操作buf中的元素
	buf2[0] = 88;
	buf2[1] = 255;
	buf2[2] = 0xaa;
	buf2[3] = 255;

    只要数字在控制台或页面中输出一定是10进制
    console.log(buf2[2].toString(16));

	for(var i=0 ; i<buf2.length ; i++){
		console.log(buf2[i]);
	}

	Buffer.allocUnsafe(size) 创建一个指定大小的buffer,但是buffer中可能含有敏感数据
	var buf3 = Buffer.allocUnsafe(10);
	console.log(buf3);

	Buffer.from(str) 将一个字符串转换为buffer
	Buffer.alloc(size) 创建一个指定大小的Buffer
	Buffer.alloUnsafe(size) 创建一个指定大小的Buffer,但是可能包含敏感数据
 	buf.toString() 将缓冲区中的数据转换为字符串

   var buf4 = Buffer.from("我是一段文本数据");

   console.log(buf4.toString());

2、简单文件写入


	 fs.writeFile(file, data[, options], callback)
	 fs.writeFileSync(file, data[, options])
		- file 要操作的文件的路径
		- data 要写入的数据
		- options 选项,可以对写入进行一些设置
		- callback 当写入完成以后执行的函数
	
		- flag
			r 只读
			w 可写
			a 追加

	//引入fs模块
	var fs = require("fs");
	
	fs.writeFile("hello3.txt","这是通过writeFile写入的内容",{flag:"r+"} , function (err) {
		if(!err){
			console.log("写入成功~~~");
		}else{
			console.log(err);
		}
	});
	
	fs.writeFile("C:/Users/zl/Desktop/hello.txt","这是通过writeFile写入的内容",{flag:"w"} , function (err) {
		if(!err){
			console.log("写入成功~~~");
		}else{
			console.log(err);
		}
	});

3、异步文件写入

	fs.open(path, flags[, mode], callback)
		- 用来打开一个文件
	   - 异步调用的方法,结果都是通过回调函数的参数返回的
		- 回调函数两个参数:
			err 错误对象,如果没有错误则为null
			fd  文件的描述符
	fs.write(fd, string[, position[, encoding]], callback)
		- 用来异步写入一个文件
	
	fs.close(fd, callback)
		- 用来关闭文件


	//引入fs模块
	var fs = require("fs");
	
	//打开文件
	fs.open("hello2.txt","w",function (err , fd) {
	
	//判断是否出错
	if(!err){
		//如果没有出错,则对文件进行写入操作
		fs.write(fd,"这是异步写入的内容",function (err) {
			if(!err){
				console.log("写入成功~~");
			}
			//关闭文件
			fs.close(fd , function (err) {
				if(!err){
					console.log("文件已关闭~~~");
				}
			});
		});
	}else{
		console.log(err);
	}
	});
	
	console.log("程序向下执行~~~");

4、流式文件写入

	同步、异步、简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出
	var fs = require("fs");
	
	
	//流式文件写入
	//创建一个可写流
	fs.createWriteStream(path[, options])
		- 可以用来创建一个可写流
		- path,文件路径
		- options 配置的参数
	
	var ws = fs.createWriteStream("hello3.txt");


    //可以通过监听流的open和close事件来监听流的打开和关闭
	on(事件字符串,回调函数)
		- 可以为对象绑定一个事件

	once(事件字符串,回调函数)
		- 可以为对象绑定一个一次性的事件,该事件将会在触发一次以后自动失效


	ws.once("open",function () {
		console.log("流打开了~~~");
	});
	
	ws.once("close",function () {
		console.log("流关闭了~~~");
	});
	
	//通过ws向文件中输出内容
	ws.write("通过可写流写入文件的内容");
	ws.write("this is a test");
	
	//关闭流
	ws.end();

5、简单文件读取

	 fs.readFile(path[, options], callback)
	 fs.readFileSync(path[, options])
	 	- path 要读取的文件的路径
	 	- options 读取的选项
	 	- callback回调函数,通过回调函数将读取到内容返回(err , data)
	 		err 错误对象
	 		data 读取到的数据,会返回一个Buffer


	var fs = require("fs");
	
	var path = "C:/Users/zl/Desktop/笔记.mp3";
	
	fs.readFile("an.jpg" , function (err , data) {
		if(!err){
			//console.log(data);
			//将data写入到文件中
			fs.writeFile("C:/Users/zl/Desktop/hello.jpg",data,function(err){
				if(!err){
					console.log("文件写入成功");
				}
			} );
		}
	});

6、流式文件读取

	流式文件读取也适用于一些比较大的文件,可以分多次将文件读取到内存中
    var fs = require("fs");

	//创建一个可读流
	var rs = fs.createReadStream("C:/Users/zl/Desktop/xx.mp3");
	//创建一个可写流
	var ws = fs.createWriteStream("a.mp3");

	//监听流的开启和关闭
	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("可写流关闭了~~");
	});

	//如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,data事件绑定完毕,它会自动开始读取数据
	rs.on("data", function (data) {
		//console.log(data);
		//将读取到的数据写入到可写流中
		ws.write(data);
	});





    或者使用流式文件的方法pipe()

	var fs = require("fs");
	//创建一个可读流
	var rs = fs.createReadStream("C:/Users/zl/Desktop/09f0sxxx.mp3");
	//创建一个可写流
	var ws = fs.createWriteStream("b.mp3");
	
	//pipe()可以将可读流中的内容,直接输出到可写流中
	rs.pipe(ws);


猜你喜欢

转载自blog.csdn.net/qq_40844662/article/details/108573527
今日推荐