LeetCode 654. Maximum Binary Tree
CMD基本知識
1.命令列視窗(小黑屏)、CMD視窗、終端、shell
- 開始選單 --> 執行 --> CMD --> 回車
- Win + R --> CMD --> 回車
- 常用的指令
dir 列出當前目錄下的所有檔案
cd 目錄名 進入到指定的目錄
md 目錄名 建立一個資料夾
rd 目錄名 刪除一個資料夾
-目錄
. 表示當前目錄
.. 表示上一級目錄
-環境變數(window系統中的變數 )
PATH
一個個的路徑
C:\Program Files\Microsoft SQL Server\130\Tools\Binn\
- 當我們在命令列視窗開啟一個檔案,或呼叫一個程式時,
系統會首先在當前目錄下尋找檔案程式,如果找到了則直接開啟
如果沒有找到則會依次到環境變數path的路徑中尋找,直到找到為止
如果沒找到則報錯
類似於作用域鏈
-所以我們可以將一些經常需要訪問的程式和檔案的路徑新增到path中,
這樣我們就可以在任意位置來訪問這些檔案和程式了
2.程序和執行緒
程序
- 程序負責為程式的執行提供必備的環境
- 程序就相當於工廠中的車間
執行緒
- 執行緒是計算機中最小的計算單位,執行緒負責執行程序中的程式
- 執行緒就相當於工廠中的工人
單執行緒
JS是單執行緒,在執行JS程式碼的時候網頁是停止渲染的。
多執行緒
主流的語言,如Java
Node.js簡介
Node.js是一個能夠在伺服器端執行JavaScript的開放原始碼、跨平臺JavaScript執行環境。
Node採用Google開發的V8引擎執行js程式碼,使用事件驅動、非阻塞和非同步I/O模型等技術來提高效能,可優化應用程式的傳輸量和規模。
Node大部分基本模組都用JavaScript編寫。在Node出現之前,JS通常作為客戶端程式設計語言使用,以JS寫出的程式常在使用者的瀏覽器上執行。
目前,Node已被IBM、Microsoft、Yahoo!、Walmart、Groupon、SAP、 LinkedIn、Rakuten、PayPal、Voxer和GoDaddy等企業採用。
Node主要用於編寫像Web伺服器一樣的網路應用,這和PHP和Python是類似的。
但是Node與其他語言最大的不同之處在於,PHP等語言是阻塞的而Node是非阻塞的。
Node是事件驅動的。開發者可以在不使用執行緒的情況下開發出一個能夠承載高併發的伺服器。其他伺服器端語言難以開發高併發應用,而且即使開發出來,效能也不盡人意。
Node正是在這個前提下被創造出來。
Node把JS的易學易用和Unix網路程式設計的強大結合到了一起。
Node.js允許通過JS和一系列模組來編寫伺服器端應用和網路相關的應用。
核心模組包括檔案系統I/O、網路(HTTP、TCP、UDP、DNS、TLS/SSL等)、二進位制資料流、加密演算法、資料流等等。Node模組的API形式簡單,降低了程式設計的複雜度。
使用框架可以加速開發。常用的框架有Express.js、Socket.IO和Connect等。Node.js的程式可以在Microsoft Windows、Linux、Unix、Mac OS X等伺服器上執行。
Node.js也可以使用CoffeeScript、TypeScript、Dart語言,以及其他能夠編譯成JavaScript的語言程式設計。
Node的用途
• Web服務API,比如REST
• 實時多人遊戲
• 後端的Web服務,例如跨域、伺服器端的請求
• 基於Web的應用
• 多客戶端的通訊,如即時通訊
簡介總結
I/O (Input/Output)
- I/O操作指的是對磁碟的讀寫操作
Node
- Node是對ES標準一個實現,Node也是一個JS引擎
- 通過Node可以使js程式碼在伺服器端執行
- Node僅僅對ES標準進行了實現,所以在Node中不包含DOM 和 BOM
- Node中可以使用所有的內建物件
String Number Boolean Math Date RegExp Function Object Array
而BOM和DOM都不能使用
但是可以使用 console 也可以使用定時器(setTimeout() setInterval())
- Node可以在後臺來編寫伺服器
Node編寫伺服器都是單執行緒的伺服器
- 程序
- 程序就是一個一個的工作計劃(工廠中的車間)
- 執行緒
- 執行緒是計算機最小的運算單位(工廠中的工人)
執行緒是幹活的
- 傳統的伺服器都是多執行緒的
- 每進來一個請求,就建立一個執行緒去處理請求
- Node的伺服器單執行緒的
- Node處理請求時是單執行緒,但是在後臺擁有一個I/O執行緒池
COMMONJS規範
ECMAScript標準的缺陷
• 沒有模組系統
• 標準庫較少
• 沒有標準介面
• 缺乏管理系統
模組化
如果程式設計的規模達到一定程度,故必須對其進行模組化
模組化可以有很多種形式,但至少應該提供能夠將程式碼分割為多個原始檔的機制
CommonJS的模組功能可以解決很多問題
CommonJS規範
1、彌補當前JS無模組化標準的缺陷;
2、希望JS能夠在任何地方執行;
3、對模組的定義較為簡單模組引用
模組定義
模組標識
模組的引用
使用require( ),該方法接手模組標識,將一個模組引入到當前的執行環境中
eg:
var math = require("math");
模組定義
在執行環境中,提供了exports物件用於匯出當前當前模組的方法或變數【它是唯一的匯出口】
模組中還存在一個module物件,它代表模組自身,而exports是module的屬性
在Node中一個檔案就是一個模組
exports.xxx = functinon(){};
module.exports = { };
模組標識
模組標識其實就是模組的名字,即傳給require()方法的引數,它必須是符合駝峰命名法的字串,或者是以.、…開頭的相對路徑、或者絕對路徑。
模組的定義十分簡單,介面也十分簡潔。每個模組具有獨立的空間,它們互不干擾,在引用時也顯得乾淨利落。
模組化總結
模組化
– 在Node中,一個js檔案就是一個模組;
– 在Node中,每一個js檔案中的js程式碼都是獨立執行在一個函式中【自執行函式】,而不是全域性作用域,所以 一個模組的變數和函式在其他模組中無法訪問
引入其他模組
用 require( ) 方法引入,引數可以傳一個檔案的路徑,如果使用相對路徑,必須以 . 或 …開頭。
引入模組以後,該函式會返回一個物件,這個物件代表的是引入的模組
*/
//var md = require("./02.module");
var math = require("./math");
var fs = require("fs");
//console.log(md);
console.log(math.add(123,456));
//console.log(fs);
02module.js
/*
我們可以通過 exports 來向外部暴露變數和方法
只需要將需要暴露給外部的變數或方法設定為exports的屬性即可
*/
//向外部暴露屬性或方法
exports.x = "我是02.module.js中的x";
exports.y = "我是y";
exports.fn = function () {
};
04module.js
/*
在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\lilichao\WebstormProjects\class0705\01.node\04.module.js
- 當前模組的完整路徑
__dirname
C:\Users\lilichao\WebstormProjects\class0705\01.node
- 當前模組所在資料夾的完整路徑
*/
//console.log(global.a);
/*
arguments.callee
- 這個屬性儲存的是當前執行的函式物件
*/
//console.log(arguments.callee + "");
//console.log(arguments.length);
//console.log(exports);
//console.log(module.exports == exports);
console.log(__dirname);
05module.js
/*
exports 和 module.exports
- 通過exports只能使用.的方式來向外暴露內部變數
exports.xxx = xxx
- 而module.exports既可以通過.的形式,也可以直接賦值
module.exports.xxx = xxxx
module.exports = {}
*/
包 package
• CommonJS的包規範允許我們將一組相關的模組組合到一起,形成一組完整的工具。
• CommonJS的包規範由包結構和包描述檔案兩個部分組成。
包結構 用於組織包中的各種檔案
包實際上就是一個壓縮檔案,解壓以後還原為目錄。符合規範的目錄,應該包含如下檔案:
package.json 描述檔案
bin 可執行二進位制檔案
lib js程式碼
doc 文件
test 單元測試
包描述檔案 描述包的相關資訊,以供外部讀取分析
包描述檔案用於表達非程式碼相關的資訊,它是一個JSON格式的檔案 – package.json,位於包的根目錄下,是包的重要組成部分。
package.json中的欄位
– name、description、version、keywords、maintainers、contributors、bugs、licenses、repositories、dependencies、homepage、os、cpu、engine、builtin、directories、implements、scripts、author、bin、main、devDependencies。
在JSON檔案不能寫註釋
NPM(Node Package Manager)
• CommonJS包規範是理論,NPM是其中一種實踐。
• 對於Node而言,NPM幫助其完成了第三方模組的釋出、安裝和依賴等。藉助NPM,Node與第三方模組之間形成了很好的一個生態系統.
NPM命令
⭐ npm install 包名 --save 安裝包並新增到依賴中 【常用】
⁉️一般我們在網上上傳包時不會上傳node_modules
【原因】
- 下載速度會很慢
-不能保證它是最新的
【注】以後在網上下載完node專案,不要立即執行,要用npm install將其所依賴的包下載下來
- npm -v 檢視版本
- npm version 檢視所有模組的版本
- npm 幫助說明
- npm search 包名 搜尋模組包
- npm remove / r 刪除包
⭐ - npm install 包名 --save 安裝包並新增到依賴中
- npm install / i 下載當前專案所依賴的包
- npm install 包名 -g 全域性安裝包(全域性安裝的包一般都是一些工具,不是在專案裡用,而是在計算機裡用,比如編譯一些css,js檔案去做專案打包)//一般用的不太多
- npm install 包名 -registry = 地址 從映象源安裝
- npm config set registry 地址 設定映象源
npm裡的一個重要命令 npm init 來生成package.json檔案
npm init -y
-y 的含義:yes的意思,在init的時候省去了敲回車的步驟,生成的預設的package.json
配置cnpm
淘寶npm映象
當我們在專案中npm install 太慢時,可以使用淘寶映象來提高npm的速度;
npm install -g cnpm --registry=https://registry.npm.taobao.org
使用上面這條命令就可以用cnpm了,用法和npm一樣。
搜尋包的流程
通過npm下載的包都放到node_modules資料夾中
我們可通過npm下載的包直接通過包名引入即可
例如:
var math = require("math");
var express = require("express");
node在使用模組名來引入模組時,它會現在當前的node_modules中尋找是否含有該模組。
如果有則直接使用,如果沒有則去上一級目錄的node_modules中尋找,直到找到為止,若直到找到磁碟的根目錄,依然沒有就會報錯;
Buffer(緩衝區)【作用:儲存二進位制資料】
• 從結構上看Buffer非常像一個數組,它的元素為16進位制的兩位數。
JS陣列效能比其他語言的陣列差
• 實際上一個元素就表示記憶體中的一個位元組。
buffer中每一個元素的範圍是從00 - ff 即0-225
計算機一個 0 或 1 稱為1為(bit)
8 bit = 1 byte(位元組)
1024 byte = 1 kb
1024 kb = 1mb
1024 mb = 1gb
1024 gb = 1 tb
var str = "Hello Atguigu";
將一個字串儲存到buffer中
var buf = Buffer.from(attr);
console.log(buf.length); 獲取的是佔用記憶體的大小 //13
console.log(str.length); 獲取的是字串的長度 //13
console.log(buf); //<Buffer 48 65 6c 6c 6f 20 41 74 67 75 69 67 75>
1
2
3
4
5
6
Buffer的大小一旦確定,則不能修改
只要數字在控制檯或頁面中輸出一定是10進位制
var buf = Buffer.alloc(10);
建立一個10位元組的buffer(即分配一個連續長度為10的空間)
通過索引,來操作buf中 的元素
var buf = Buffer.alloc(10); //alloc創造10個位元組的空間同時會把資料清空
buf[0] = 88;
buf[1] = 255;
buf[2] = 0xaa;
buf[3] = 556;
console.log(buf); 結果:<Buffer 58 ff aa 2c 00 00 00 00 00 00>【2c 是一個位元組只有8個bit,溢位時只取後8位得出對應16制的2c】
var buf1 = Buffer.allocUnsafe(10);//效能好,但可能洩露資料
console.log(buf1);//<Buffer 00 00 00 00 00 00 00 00 3f 00>
var buf = Buffer.from("言人冰");
console.log(buf.toString());//資料轉換成字串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
• 實際上Buffer中的記憶體不是通過JavaScript分配的,而是在底層通過C++申請的。
• 也就是我們可以直接通過Buffer來建立記憶體中的空間。
Buffer與字串間的轉換
– 支援的編碼:
• ASCII、UTF-8、UTF-16LE/UCS-2、Base64、Binary、Hex
– 字串轉Buffer
• Buffer.from(str , [encoding]);
– Buffer轉字串
• buf.toString([encoding] , [start] , [end]);
寫入操作
• 向緩衝區中寫入字串
– buf.write(string[, offset[, length]][, encoding])
• 替換指定索引位置的資料
– buf[index]
• 將指定值填入到緩衝區的指定位置
– buf.fill(value[, offset[, end]][, encoding])
讀取操作
• 將緩衝區中的內容,轉換為一個字串返回
– buf.toString([encoding[, start[, end]]])
• 讀取緩衝區指定索引的內容
– buf[index]
其他操作
• 複製緩衝區
– buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
• 對緩衝區切片
– buf.slice([start[, end]])
• 拼接緩衝區
– Buffer.concat(list[, totalLength])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
總結:
Buffer.from(str) 將一個字串轉換為buffer
Buffer.alloc(size) 建立一個指定大小的Buffer
Buffer.alloUnsafe(size) 建立一個指定大小的Buffer,但是可能含敏感資料
把緩衝區的資料轉換為字串
buf.toString( )將緩衝區的資料轉換為字串
fs(檔案系統)
簡單來講就是通過node來作業系統中的檔案
使用檔案系統,需要引入fs模組,fs是核心模組,直接引入不需要下載
同步和非同步呼叫
fs模組中所有的操作都有兩種形式可供選擇同步和非同步。
同步檔案系統會阻塞程式的執行,也就是除非操作完畢,否則不會向下執行程式碼。
非同步檔案系統不會阻塞程式的執行,而是在操作完成時,通過回撥函式將結果返回。
非同步操作寫法雖然有點麻煩,但效能較同步操作的好。而同步操作沒有考慮異常的操作,所以一旦一步錯問題後續的都無了!
開啟和關閉檔案
• 開啟檔案
– fs.open(path, flags[, mode], callback)
– fs.openSync(path, flags[, mode])
1
2
• 關閉檔案
– fs.close(fd, callback)
– fs.closeSync(fd)
1
2
開啟狀態
寫入檔案
- fs中提供了四種不同的方式將資料寫入檔案
– 1. 簡單檔案寫入
– 2. 同步檔案寫入
– 3. 非同步檔案寫入
– 4. 流式檔案寫入
簡單檔案寫入
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])
引數:
– file 檔案路徑
– data 被寫入的內容,可以是String或Buffer
– options 物件,包含屬性(encoding、mode、flag)
– callback 回撥函式
簡單檔案的寫入
var fs = require("fs");
fs.writeFile("hello.txt","啦啦啦",{flag:"w"},(err)=>{
if(!err)console.log("寫入成功");
});
1
2
3
4
5
6
同步檔案的寫入
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 寫入編碼
同步檔案的寫入
-手動操作的步驟
1.開啟檔案
fs.openSync(path,flags[,mode])
-path 要開啟檔案的路徑
-flags 開啟檔案要做的操作型別
r 只讀的
w 可寫的
- mode 設定檔案的操作許可權,一般不傳
返回值:
-該方法會返回一個檔案的描述符作為結果,可以通過該描述符進行各種操作
2.向檔案中寫入內容
fs.writeSync(fd, string[, position[, encoding]])
- fd 檔案的描述符,需要傳遞要寫入的檔案的描述符
- string 要寫入的內容
- position 表示起始的位置[一般不傳]
- encoding 寫入的編碼,預設utf-8
3.儲存並關閉檔案
fs.closeSync(fd)
- fd 要關閉檔案的描述符
var fs = require("fs");
//開啟檔案
var fd = fs.openSync("hello.txt","w");
//向檔案中寫入內容
fs.writeSync(fd,"love",4);
//關閉檔案
fs.closeSync(fd);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
非同步檔案的寫入
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 寫入編碼
非同步檔案的寫入
非同步檔案開啟
fs.open(path[, flags[, mode]], callback)
不會返回fd(檔案的描述符),而是會在回撥函式中顯示,回撥函式有兩個引數fd,和err
非同步檔案寫入
fs.write(fd, string[, position[, encoding]], callback)
非同步檔案關閉
fs.close(fd[, callback])
var fs = require("fs");
fs.open("hello.txt","w",function(err,fd){
if(!err){ //如果沒有出錯,則繼續向文件寫入內容
fs.write(fd,"我是hello.txt中的內容",function(err){
if(!err){
console.log("寫入成功!!!");
}
fs.close(fd,function(err){
if(!err){
console.log("檔案關閉成功!!!");
}
});
});
}else{
console.log("fail to open the file!");
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
流式檔案寫入
往一個檔案中寫入大量資料時,最好的方法之一是使用流。
若要將資料非同步傳送到檔案,首需要使用以下語法建立一個Writable物件:
– fs.createWriteStream(path[, options])
path 檔案路徑
options {encoding:"",mode:"",flag:""}
一旦你打開了Writable檔案流,就可以使用write()方法來寫入它,寫入完成後,在呼叫end()方法來關閉流。
同步、非同步、簡單檔案的寫入都不適合大檔案的寫入,效能較差,容易導致記憶體溢位
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("今天天氣真不錯");
ws.write("鋤禾日當午");
ws.write("紅掌撥清清");
ws.write("清清真漂亮");
//關閉流,關閉寫的那個檔案的管口
ws.end();
//關閉流,關閉讀的那個檔案的管口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
讀取檔案
fs中提供了四種讀取檔案的方式
– 簡單檔案讀取
– 同步檔案讀取
– 非同步檔案讀取
– 流式檔案讀取
簡單檔案讀取
fs.readFile(file[, options], callback)
fs.readFileSync(file[, options])
– 引數:
file 檔案路徑或檔案描述符
options |
– encoding | 預設 = null
– flag 預設 = ‘r’
callback 回撥函式,有兩個引數err 、data
同步檔案讀取
• fs.readSync(fd, buffer, offset, length, position)
– 引數:
• fd 檔案描述符
• buffer 讀取檔案的緩衝區
• offset buffer的開始寫入的位置
• length 要讀取的位元組數
• position 開始讀取檔案的位置
非同步檔案讀取
• fs.read(fd, buffer, offset, length, position, callback)
– 引數:
• fd 檔案描述符
• buffer 讀取檔案的緩衝區
• offset buffer的開始寫入的位置
• length 要讀取的位元組數
• position 開始讀取檔案的位置
• callback 回撥函式 引數err , bytesRead , buffer
流式檔案讀取
• 從一個檔案中讀取大量的資料時,最好的方法之一就是流式讀取,這樣將把一個檔案作為Readable流的形式開啟。
• 要從非同步從檔案傳輸資料,首先需要通過以下語法建立一個Readable流物件:
– fs.createReadStream(path[, options])
• path 檔案路徑
• options {encoding:"",mode:"",flag:""}
• 當你開啟Readable檔案流以後,可以通過readable事件和read()請求,或通過data事件處理程式輕鬆地從它讀出。
其他操作
• 驗證路徑是否存在
– fs.exists(path,callback)
– 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)
簡單檔案、同步檔案、非同步檔案、流式檔案的讀取
/*
1.同步檔案讀取
2.非同步檔案讀取
3.簡單檔案讀取
fs.readFile(path[, options], callback)
fs.readFileSync(path[, options])
- path 要讀取的檔案的路徑
- options 讀取的選項
- callback回撥函式,通過回撥函式將讀取到內容返回(err , data)
err 錯誤物件
data 讀取到的資料,會返回一個Buffer
4.流式檔案讀取
*/
var fs = require("fs");
var path = "C:/Users/lilichao/Desktop/筆記.mp3";
fs.readFile("an.jpg" , function (err , data) {
if(!err){
//console.log(data);
//將data寫入到檔案中
fs.writeFile("C:/Users/lilichao/Desktop/hello.jpg",data,function(err){
if(!err){
console.log("檔案寫入成功");
}
} );
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
流式檔案的讀取
流式檔案讀取也適用於一些比較大的檔案,可以分多次將檔案讀取到記憶體中
var fs = require("fs");
//建立一個可讀流
var rs = fs.createReadStream("C:/Users/lilichao/Desktop/筆記.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);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
流式檔案讀取也適用於一些比較大的檔案,可以分多次將檔案讀取到記憶體中
var fs = require("fs");
//建立一個可讀流
var rs = fs.createReadStream("C:/Users/lilichao/Desktop/筆記.mp3");
//建立一個可寫流
var ws = fs.createWriteStream("b.mp3");
//pipe()可以將可讀流中的內容,直接輸出到可寫流中
rs.pipe(ws);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
《node.js總結》
node
- 包(package)
- 將多個模組組合為一個完整的功能,就是一個包
- 包結構
bin
- 二進位制的可執行檔案,一般都是一些工具包中才有
lib
- js檔案
doc
- 文件
test
- 測試程式碼
package.json
- 包的描述檔案
- package.json
- 它是一個json格式的檔案,在它裡面儲存了包各種相關的資訊
name 包名
version 版本
dependencies 依賴
main 包的主要的檔案
bin 可執行檔案
- npm(Node Package Manager node的包管理器)
- 通過npm可以對node中的包進行上傳、下載、搜尋等操作
- npm會在安裝完node以後,自動安裝
- npm的常用指令
npm -v 檢視npm的版本
npm version 檢視所有模組的版本
npm init 初始化專案(建立package.json)
npm i/install 包名 安裝指定的包
npm i/install 包名 --save 安裝指定的包並新增依賴
npm i/install 包名 -g 全域性安裝(一般都是一些工具)
npm i/install 安裝當前專案所依賴的包
npm s/search 包名 搜尋包
npm r/remove 包名 刪除一個包
檔案系統(File System)
- Buffer(緩衝區)
- Buffer和陣列的結構的非常類似,Buffer是用來儲存二進位制資料的
- Buffer的方法
- Buffer.from(字串)
- 將一個字串中內容儲存到一個buffer中
- buf.toString()
- 將buffer轉換為一個字串
- Buffer.alloc(size)
- 建立一個指定大小的buffer物件
- Buffer.allocUnsafe(size)
- 建立一個指定大小的buffer物件,可以包含敏感資料
- fs模組
- 在Node通過fs模組來對系統中的檔案進行操作,fs模組是node中已經繼承好了,不需要在使用npm下載,直接引入即可
- 引入fs
var fs = require("fs");
- fs模組中的大部分操作都提供了兩種方法,同步方法和非同步方法
同步方法帶sync
非同步方法沒有sync,都需要回調函式
- 寫入檔案
1.同步寫入
2.非同步寫入
3.簡單寫入
4.流式寫入
- 讀取檔案
1.同步讀取
2.非同步讀取
3.簡單讀取
4.流式讀取
- 方法
- 開啟檔案
fs.open(path, flags[, mode], callback)
fs.openSync(path, flags[, mode])
- 讀寫檔案
fs.write(fd, string[, position[, encoding]], callback)
fs.writeSync(fd, string[, position[, encoding]])
fs.read(fd, buffer, offset, length, position, callback)
fs.readSync(fd, buffer, offset, length, position)
- 關閉檔案
fs.close(fd,callback)
fs.closeSync(fd);
- 簡單檔案讀取和寫入
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])
fs.readFile(path[, options], callback)
fs.readFileSync(path[, options])
- 流式檔案讀取和寫入
- 流式讀取和寫入適用於一些比較大的檔案
fs.createWriteStream(path[, options])
fs.createReadStream(path[, options])