一绰精、核心模塊和對象
- 核心模塊的意義
- 如果只是在服務器運行JavaScript代碼察绷,意義并不大洲胖,因為無法實現(xiàn)任何功能(讀寫文件,訪問網(wǎng)絡)鹊杖。
- Node 的用處在于它本身還提供的一系列功能模塊悴灵,用于與操作系統(tǒng)互動。
- 這些核心的功能模塊在 Node 中內(nèi)置骂蓖。
- 常用內(nèi)置模塊
- path:處理文件路徑
- fs:操作文件系統(tǒng)
- child_process:新建子進程
- util:提供一系列實用小工具
- http:提供HTTP服務器功能
- url:用于解析URL
- querystring:解析URL中的查詢字符串
- crypto:提供加密和解密功能
- 其他
二积瞒、文件系統(tǒng)操作
- 相關模塊的使用
- fs: 基礎的文件操作 API
- path: 提供和路徑相關的操作 API
- readline: 用于讀取大文本文件,一行一行讀
- fs-extra(第三方文件操作模塊): https://www.npmjs.com/package/fs-extra
- path模塊的使用
在文件操作的過程中登下,都必須使用物理路徑(絕對路徑)茫孔,path模塊提供了一系列與路徑相關的 API;
// path.basename(path[, ext])
// 獲取文件名(包含后綴)
console.log(path.basename(temp));
// 獲取文件名(不包含后綴) 第二個參數(shù)即要刪除的后綴
console.log(path.basename(temp, '.lrc'));
// path.delimiter
// 獲取不同操作系統(tǒng)中默認的路徑分隔符
// windows是分號,Linux是冒號
console.log(path.delimiter);
// 獲取環(huán)境變量
console.log(process.env.PATH);
// 將對應環(huán)境變量分割
console.log(process.env.PATH.split(path.delimiter));
// path.dirname(path)
// 獲取目錄名稱
console.log(path.dirname(temp));
// path.extname(path)
// 獲取后綴名被芳,包含點(在path.basename中就有ext)
console.log(path.extname(temp));
// path.parse(path)
// 將路徑字符串轉(zhuǎn)為對象(文件根目錄缰贝、文件路徑、文件全名(帶后綴)畔濒、后綴名剩晴、文件名(不帶后綴))
console.log(path.parse(temp));
// path.format(pathObject)
// 路徑對象轉(zhuǎn)字符串
console.log(path.format( path.parse(temp) ));
// path.isAbsolute(path)
// 判斷是否為絕對路徑
console.log(path.isAbsolute(temp));
// path.join([...paths])
// 路徑拼接
const temp = path.join(__dirname, './lyrics/相依為命.lrc');
// path.normalize(path)
// 常規(guī)化一個路徑(將多余的斜杠處理,)
var urlStr = 'C:/System32\\a//test///haha.html';
console.log(path.normalize(urlStr));
// path.relative(from, to)
// 獲取to相對于from的相對路徑
console.log(path.relative(__dirname, '/Users/test/Desktop/03-文件系統(tǒng)操作/haha.html'));
// path.resolve([...paths])
// 類似于join的字符串拼接
console.log(path.resolve(__dirname, '../', '../', 'haah.html'));
// 與join不一樣的(不是簡單的字符串拼接)
console.log(path.resolve(__dirname, '/User/test', 'hehe', 'haha.html')); // 輸出結果是/User/test/hehe/haha.html
- 同步或異步調(diào)用
- fs模塊對文件的幾乎所有操作都有同步和異步兩種形式
- 例如:readFile() 和 readFileSync()
- 同步調(diào)用會阻塞代碼的執(zhí)行侵状,異步則不會
- 異步調(diào)用會將讀取任務下達到任務隊列赞弥,直到任務執(zhí)行完成才會回調(diào)
- 異常處理方面,同步必須使用 try catch 方式趣兄,異步可以通過回調(diào)函數(shù)的第一個參數(shù)
- 文件讀取
- 異步文件讀取
fs.readFile(file[, options], callback(error, data))
- 異步文件讀取
// 讀取時有設置編碼utf8
fs.readFile(path.join(__dirname, './test.txt'), 'utf8', (error, data)=>{
if(error) throw error;
console.log(`異步: ${data}`);
});
- 同步文件讀取
fs.readFileSync(file[, options])
// 同步操作的寫法绽左,錯誤是通過拋出異常
try {
var data = fs.readFileSync(path.join(__dirname, './test.txt'), 'utf8');
console.log(`同步: ${data}`);
} catch (error) {
throw error;
}
node默認編碼類型是utf8;
由于Windows平臺下默認文件編碼是GBK艇潭,在node中是不支持的gbk類型編碼的!!!!
對于各種操作系統(tǒng)中編碼問題,可以通過iconv-lite解決
- 文件流的方式讀取
fs.createReadStream(path[, options])
const stream = fs.createReadStream('1.txt');
let data = ' '
stream.on('data', (trunk) => {
data += trunk;
});
stream.on('end', () => {
console.log(data);
});
流的方式Stream模塊拼窥。pipe管道,可以將讀取到流蹋凝,導入到另外一個目標中鲁纠,還可以設置流的類型;
fs.createReadStream(filename)假如該文件流數(shù)據(jù)類型是utf8 通過pipe仙粱,將流的類型改變gbk fs.createReadStream(filename).pipe(iconv.decodeStream('gbk'))
- 模塊逐行讀取文本
readline
const readline = require('readline');
const fs = require('fs');
const rl = readline.createInterface({input: fs.createReadStream('sample.txt') });
rl.on('line', (line) => {
console.log('Line from file:', line);
});
正則表達式: objReg.exec(string) 該函數(shù)通過對指定你的字符串進行一次匹配檢測房交,獲取字符串中的第一個與正則表達式的內(nèi)容,并且將匹配的內(nèi)容和子匹配的結果存放在返回數(shù)組中
var rel = /^\[\d{2}\:\d{2}\.\d{2,4}\].+$/;
var rel = /^\[(\d{2})\:(\d{2})\.(\d{2,4})\](.+)$/; // 有括號的即為子分組
rel.exec(line)
> 案例: 歌詞滾動
案例: 根據(jù)歌曲時間顯示對應歌詞
- 文件寫入
- 異步文件寫入
fs.writeFile(file,data[,option],callback(err))
- 異步文件寫入
fs.writeFile(path.join(__dirname, './temp.txt'), JSON.stringify({id: 10}), (err) => {
if(err){
// 一般寫文件伐割,如果出現(xiàn)錯誤候味,都是因為權限問題(權限不夠不能創(chuàng)建文件)
// 文件夾如果不存在刃唤,不會創(chuàng)建文件夾,也會出錯
console.log('err:' + err);
} else {
console.log('文件寫入成功');
}
});
- 同步文件寫入
fs.writeFileSync(file,data,[,option])
fs.writeFileSync(path.join(__dirname, 'temp.txt'), '你好?');
- 流式文件寫
fs.createWriteStream(path[,option])
fs.createWriteStream();
var streamWriter = fs.createWriteStream(path.join(__dirname, 'temp.txt'));
// 是屬于非阻塞的streamWriter.write白群,返回true/false
console.log( streamWriter.write('哈哈', ()=>{
console.log('+1');
}) );
默認寫入操作是覆蓋源文件
- pipe管道方式(文件讀寫操作)
var readstream = fs.createReadStream('01-path.js');
var writestream = fs.createWriteStream('test4.txt');
// 直接將讀文件流 導入到 寫文件流中
readstream.pipe(writestream);
- 異步追加
fs.appendFile(file,data[,options],callback(err))
fs.appendFile(path.join(__dirname, 'temp.txt'), ' 測試', (err)=>{
if(err){
console.log('error: ' + err);
} else {
console.log('追加成功');
}
});
- 同步追加
fs.appendFileSync(file,data[,options])
fs.appendFileSync(path.join(__dirname, 'temp.txt'), ' 追加成功了嗎?');
- 文件其他操作
- 獲取文件信息
fs.stat(path,callback(err,stats))
fs.statSync(path) // => 返回一個fs.Stats實例
- 獲取文件信息
fs.stat('temp.txt', (err, stats)=>{
if(err){
console.log('err:' + err);
} else {
console.log(stats.isFile());
}
});
讀取到文件信息后尚胞,可以判斷文件的類型
stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink()
stats.isSocket()
- 移動文件、重命名文件或目錄
fs.rename(oldPath,newPath,callback)
fs.renameSync(oldPath,newPath)
fs.rename('temp.txt', 'test.txt', (err)=>{
if(err){
console.log('err:' + err);
} else {
console.log('修改文件名成功');
}
});
- 刪除文件
fs.unlink(path,callback(err))
fs.unlinkSync(path)
fs.unlink('test.txt', (err)=>{
if(err){
console.log('err:' + err);
} else {
console.log('刪除文件名成功');
}
});
- 目錄操作
- 創(chuàng)建一個目錄
fs.mkdir(path[,model],callback)
fs.mkdirSync(path[,model])
- 創(chuàng)建一個目錄
fs.mkdir(path.join(__dirname, 'test.txt'), (err)=>{
if(err){
console.log(err);
} else {
console.log('創(chuàng)建文件成功');
}
});
- 刪除一個空目錄
fs.rmdir(path,callback)
fs.rmdirSync(path)
fs.rmdir(path.join(__dirname, 'test.txt'), (err)=>{
if(err){
console.log('err:' + err);
}else{
console.log('刪除成功');
}
});
- 讀取一個目錄
fs.readdir(path,callback(err,files))
fs.readdirSync(path) // => 返回files
fs.readdir(__dirname, (err, files)=>{
if(err){
console.log('err:' + err);
}else{
console.log(files);
}
});
三帜慢、緩沖區(qū)
- 什么是緩沖區(qū)
- 緩沖區(qū)就是內(nèi)存中操作數(shù)據(jù)的容器
- 只是數(shù)據(jù)容器而已
- 通過緩沖區(qū)可以很方便的操作二進制數(shù)據(jù)
- 而且在大文件操作時必須有緩沖區(qū)
為什么要有緩沖區(qū)
JavaScript是比較擅長處理字符串笼裳,但是早期的應用場景主要用于處理HTML文檔,不會有太大篇幅的數(shù)據(jù)處理粱玲,也不會接觸到二進制的數(shù)據(jù)躬柬。而在Node中操作數(shù)據(jù)、網(wǎng)絡通信是沒辦法完全以字符串的方式操作的抽减,所以在Node中引入了一個二進制的緩沖區(qū)的概念:Buffer允青。緩沖區(qū)簡單操作
// 創(chuàng)建長度為4個字節(jié)的緩沖區(qū)
var buffer = new Buffer(4);
// 通過指定編碼的方式創(chuàng)建
var buffer = new Buffer('hello', 'utf8');
// 往緩沖區(qū)中寫數(shù)據(jù)(假如緩沖區(qū)只有4個字節(jié)大小)
buffer.write('123456');
console.log(buffer.toString('utf8')); // 輸出是1234
node中默認的編碼類型都是utf-8;
- 讀圖片操作
var fs = require('fs');
var path = require('path');
fs.readFile(path.join(__dirname, './test.png'), (error, data)=>{
if(error) console.error(error);
// 將buffer內(nèi)容讀取出來(圖片是base64)
console.log(data.toString('base64'));
});
還原生成Base64編碼為圖片: http://www.atool.org/img2base64.php;
注意: 要在前面添加上data:image/png;base64,
表示圖片類型;
- node支持的編碼
Buffers 和 JavaScript 字符串對象之間轉(zhuǎn)換時需要一個明確的編碼方法卵沉。
- 'ascii' - 7位的 ASCII 數(shù)據(jù)颠锉。這種編碼方式非常快史汗,它會移除最高位內(nèi)容
- 'utf8' - 多字節(jié)編碼 Unicode 字符琼掠。大部分網(wǎng)頁和文檔使用這類編碼方式
- 'utf16le' - 2個或4個字節(jié), Little Endian (LE) 編碼 Unicode 字符。編碼范圍 (U+10000 到 U+10FFFF)
- 'ucs2' - 'utf16le'的子集
- 'base64' - Base64 字符編碼
- 'binary' - 僅使用每個字符的頭8位將原始的二進制信息進行編碼
(在需使用 Buffer 的情況下停撞,應該盡量避免使用這個已經(jīng)過時的編碼方式瓷蛙,這個編碼方式將會在未來某個版本中棄用)。
- 'hex' - 每個字節(jié)都采用 2 進制編碼戈毒。
在node中是不支持的gbk類型編碼的!!!!
對于各種操作系統(tǒng)中編碼問題速挑,可以使用第三方模塊iconv-lite