Buffer緩衝區
JavaScript 語言自身只有字符串數據類型,沒有二進制數據類型,所以Buffer就是用來存儲二進制文件的。
但在處理像TCP流或文件流時,必須使用到二進制數據。因此在 Node.js中,定義了一個 Buffer 類,該類用來創建一個專門存放二進制數據的緩存區。一個 Buffer 類似於一個整數數組,但它對應於 V8 堆內存之外的一塊原始內存。
在v6.0之前創建Buffer對象直接使用new Buffer()構造函數來創建對象實例,但是Buffer對內存的權限操作相比很大,可以直接捕獲一些敏感信息,所以在v6.0以後,官方文檔裏面建議使用 Buffer.from() 接口去創建Buffer對象
Buffer 與字符編碼
Buffer 實例一般用於表示編碼字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六進制編碼的數據。 通過使用顯式的字符編碼,就可以在 Buffer 實例與普通的 JavaScript 字符串之間進行相互轉換。
在緩衝區和字符串之間進行轉換時,可以指定字符編碼。如果沒有指定字符編碼,將使用UTF-8作爲默認值。
const buf = Buffer.from('runoob', 'ascii');
// 輸出 72756e6f6f62
console.log(buf.toString('hex'));
// 輸出 cnVub29i
console.log(buf.toString('base64'));
Node.js 目前支持的字符編碼包括:
-
ascii - 僅支持 7 位 ASCII 數據。如果設置去掉高位的話,這種編碼是非常快的。
-
utf8 - 多字節編碼的 Unicode 字符。許多網頁和其他文檔格式都使用 UTF-8 。
-
utf16le - 2 或 4 個字節,小字節序編碼的 Unicode 字符。支持代理對(U+10000 至 U+10FFFF)。
-
ucs2 - utf16le 的別名。
-
base64 - Base64 編碼。
-
latin1 - 一種把 Buffer 編碼成一字節編碼的字符串的方式。
-
binary - latin1 的別名。
-
hex - 將每個字節編碼爲兩個十六進制字符。
Buffer 使用
直接使用不需要引入模塊,直接使用即可。
Buffer
類是一個全局變量,用於直接處理二進制數據。 它可以使用多種方式構建。
Buffer.from(array)#
新增於: v5.10.0
array
<integer[]>
使用 0
– 255
範圍內的字節數組 array
來分配一個新的 Buffer
。 超出該範圍的數組條目會被截斷以適合它。
// 創建一個包含字符串 'buffer' 的 UTF-8 字節的新 Buffer。
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
如果 array
不是一個 Array
或適用於 Buffer.from()
變量的其他類型,則拋出 TypeError
。
Buffer.from(array)
和 Buffer.from(string)
也可以像 Buffer.allocUnsafe()
一樣使用內部的 Buffer
池。
Buffer.alloc(size[, fill[, encoding]])
size
<integer> 新Buffer
的所需長度。fill
<string> | <Buffer> | <Uint8Array> | <integer> 用於預填充新Buffer
的值。默認值:0
。encoding
<string> 如果fill
是一個字符串,則這是它的字符編碼。默認值:'utf8'
。
const b = Buffer.alloc(10,"李連杰","utf8");
console.log(b.toString());
Buffer.allocUnsafe(size)
size
<integer> 新建的Buffer
的長度。
創建一個大小爲 size
字節的新 Buffer
。 如果 size
大於 buffer.constants.MAX_LENGTH
或小於 0,則拋出 ERR_INVALID_OPT_VALUE
。
以這種方式創建的 Buffer
實例的底層內存是未初始化的。 新創建的 Buffer
的內容是未知的,可能包含敏感數據。 使用 Buffer.alloc()
可以創建以零初始化的 Buffer
實例。
const buf = Buffer.allocUnsafe(10);
console.log(buf);
// 打印(內容可能有所不同): <Buffer a0 8b 28 3f 01 00 00 00 50 32>
buf.fill(0);
console.log(buf);
// 打印: <Buffer 00 00 00 00 00 00 00 00 00 00>
對比Buffer.alloc(size[, fill[, encoding]])和Buffer.allocUnsafe(size)
alloc:安全,效率低
allocUnsafe:不安全,效率高,會泄露敏感信息。
fs的同步和異步調用:
- fs模塊中所有的操作都有兩種形式可以選擇,同步和異步。
- 同步晚間系統會阻塞程序的運行,也就是除非操作完畢,否則不會向下執行代碼。
- 異步文件系統不會阻塞程序的執行,二是在操作完成時,通過回調函數將結果返回。
fs寫入文件
同步文件寫入
1.打開文件
fs.openSync(path[, flags, mode])
'r'就是隻讀
'w'就是可寫
。
設置文件的操作權限,一般用於Linux。
- 返回: <number>返回表示文件描述符的整數。
返回一個描述符,相當於標誌,實際值沒有意義,就相當於給你打開的文件起個別名,以後你就可以將其作爲這個文件的標誌。
2.寫入文件
fs.writeSync(fd, string[, position[, encoding]])
fd
<integer> 文件描述符,需要傳遞要寫入文件的文件描述符
3.關閉文件
fs.closeSync(fd)
fd
<integer>
同步的 close(2)
。返回 undefined
。
通過任何其他 fs
操作在當前正在使用的任何文件描述符(fd
)上調用 fs.closeSync()
可能導致未定義的行爲。
fs同步寫入文件
//引入fs模塊
const fs = require("fs");
//打開一個文件
var file = fs.openSync("./hello.txt",'w');
console.log("文件描述符:"+file);
fs.writeSync(file,"今天很高興學習fs文件寫入!");
fs.closeSync(file);
fs異步寫入文件
1.打開文件
fs.open(path[, flags[, mode]], callback)
path
<string> | <Buffer> | <URL>
flags
<string> | <number> 參見文件系統flag
的支持。 默認值:'r'
。mode
<string> | <integer> 默認值:0o666
(可讀寫)。-
callback
<Function>
mode
用於設置文件模式(權限和粘滯位),但僅限於創建文件時。 在 Windows 上,只能操作寫權限,參見 fs.chmod()
。
回調有兩個參數 (err, fd)
。
有些字符 (< > : " / \ | ? *
) 在 Windows 上是預留的,參見命名文件、路徑以及命名空間。 在 NTFS 上,如果文件名包含冒號,則 Node.js 會打開文件系統流,參見此 MSDN 頁面。
基於 fs.open()
的函數也會表現出以上行爲,比如 fs.writeFile()
、 fs.readFile()
等。
//引入fs模塊
const fs = require("fs");
//打開一個文件
fs.open("./hello2.txt","w",function (error,fd) {
console.log("文件描述符:"+fd);
if(error){
console.log(error);
}else{
fs.writeSync(fd,"今天很高興學習fs文件寫入!");
}
fs.closeSync(fd);
})
簡單文件寫入
異步
fs.writeFile(file, data[, options], callback)
file
<string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。data
<string> | <Buffer> | <TypedArray> | <DataView>-
encoding
<string> | <null> 默認值:'utf8'
。mode
<integer> 默認值:0o666
。flag
<string> 參見文件系統flag
的支持。 默認值:'w'
。
-
callback
<Function>err
<Error>
當 file
是文件名時,則異步地寫入數據到文件(如果文件已存在,則覆蓋文件)。 data
可以是字符串或 buffer。
當 file
是文件描述符時,則其行爲類似於直接調用 fs.write()
(建議使用)。 參見以下關於使用文件描述符的說明。
如果 data
是 buffer,則 encoding
選項會被忽略。
const data = new Uint8Array(Buffer.from('Node.js 中文網'));
fs.writeFile('文件.txt', data, (err) => {
if (err) throw err;
console.log('文件已被保存');
});
//引入fs模塊
const fs = require("fs");
//寫入一個文件
fs.writeFile("hello3.txt","這是通過writeFile寫入的內容",function (error) {
if(!error){
console.log("寫入成功:");
}
})
同步
fs.writeFileSync(file, data[, options])
file
<string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。data
<string> | <Buffer> | <TypedArray> | <DataView> 要寫入的數據-
encoding
<string> | <null> 默認值:'utf8'
。mode
<integer> 默認值:0o666
。flag
<string> 參見文件系統flag
的支持。 默認值:'w'
。
返回 undefined
。
//引入fs模塊
const fs = require("fs");
//打開文件
fs.open('hello4.txt', 'a', function(err,fd){
if(err){
throw err;
}
var data = '同步簡單寫入';
var buf = new Buffer(8);
fs.writeSync(fd, buf, 0, 8, 0);
fs.close(fd,function(err){
if(err){
throw err;
}
console.log('file closed');
})
})
流式文件寫入
1創建一個可寫流
fs.createWriteStream(path[, options])
path
<string> | <Buffer> | <URL> 文件路徑- 返回: <fs.WriteStream>
2通過可寫流寫入內容
//流式文件寫入
const fs = require("fs");
//創建可寫流
const fw = fs.createWriteStream("hello.txt");
//通過可寫流寫入內容
fw.write("通過可寫流寫入文件的內容0");
fw.write("通過可寫流寫入文件的內容1");
fw.write("通過可寫流寫入文件的內容2");
fw.once("open",function () {
console.log("流打開了~~~");
})
//關閉輸出方的流
fw.end();
注意:流式寫入關閉的時候要關閉輸入方的流,不能關閉接受方的流,因爲寫入方只需將內容傳送到流(水管)中就可以關閉了,但是如果接受方關閉流的話,就相當於主動拔掉水管不接受水管中的內容。
fs讀取文件
同步
fs.readFileSync(path[, options])
path
<string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。-
encoding
<string> | <null> 默認值:null
。flag
<string> 參見文件系統flag
的支持。 默認值:'r'
。
- 返回: <string> | <Buffer>
返回 path
的內容。
異步:
fs.readFile(path[, options], callback)
#
path
<string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。-
encoding
<string> | <null> 默認值:null
。flag
<string> 參見文件系統flag
的支持。默認值:'r'
。
-
callback
<Function>
異步地讀取文件的全部內容。
同步和異步如下:
var fs = require('fs');
//導入文件模塊
//node 同步讀文件
var sycContext = fs.readFileSync("hello.txt",{flag:'r',encoding:"UTF-8"});
console.log(content.toString());
//node 異步讀文件,
var content = fs.readFile("hello.txt",{flag:'r',encoding:"UTF-8"},function (err,data) {
if(err){
console.log(err);
}else{
console.log(data);
}
});
簡單文件讀取
const fs = require("fs");
const path = "zz.jpg";
const content = fs.readFile(path,{flag:'r'},function (err,data) {
if(err){
console.log(err);
}else{
fs.writeFile("dog.jpg",data,function () {
console.log(data);
})
}
});
流式文件讀取
如果要讀取一個可讀流中的數據,必須腰圍可讀流綁定一個事件,data事件綁定完畢,它會自動開始讀取數據。
const fs = require("fs");
const fr = fs.createReadStream("hello.txt");
fr.once("open",function () {
console.log("流打開了");
})
fr.on("data",function (data) {
console.log(data,data.length);
})
fr.once("close",function () {
console.log("流關閉了");
})
文件操作狀態
模式 |
說明 |
r |
讀取文件,文件不存在則出現異常 |
r+ |
讀寫文件,文件不存在則出現異常 |
rs |
在同步模式下打開文件用於讀取 |
rs+ |
在同步模式下打開文件用於讀取 |
w |
打開文件用於寫操作,如果不存在則創建,如果存在則截斷(幹掉) |
wx |
打開文件用於寫操作,如果存在則打開失敗 |
w+ |
打開文件用於讀寫,如果不存在則創建,如果存在則截斷(幹掉) |
wx+ |
打開文件用於讀寫,如果存在則打開失敗 |
a |
打開文件用於追加,如果不存在則創建 |
ax |
打開文件用於追加,如果文件路徑存在則失敗 |
a+ |
打開文件進行讀取和追加,如果不存在則創建該文件 |
ax+ |
打開文件進行讀取和追加,如果路徑存在則失敗 |