1. 程式人生 > >Node.js本地檔案操作之檔案拷貝與目錄遍歷的方法

Node.js本地檔案操作之檔案拷貝與目錄遍歷的方法

檔案拷貝
NodeJS 提供了基本的檔案操作 API,但是像檔案拷貝這種高階功能就沒有提供,因此我們先拿檔案拷貝程式練手。與 copy 命令類似,我們的程式需要能接受原始檔路徑與目標檔案路徑兩個引數。

小檔案拷貝
我們使用 NodeJS 內建的 fs 模組簡單實現這個程式如下。

1 2 3 4 5 6 7 8 9 10 11 var fs = require('fs'); function copy(src, dst) { fs.writeFileSync(dst, fs.readFileSync(src)); } function main(argv) { copy(argv[0], argv[1]);
} main(process.argv.slice(2));

以上程式使用 fs.readFileSync 從源路徑讀取檔案內容,並使用 fs.writeFileSync 將檔案內容寫入目標路徑。

豆知識: process 是一個全域性變數,可通過 process.argv 獲得命令列引數。由於 argv[0] 固定等於 NodeJS 執行程式的絕對路徑,argv[1] 固定等於主模組的絕對路徑,因此第一個命令列引數從 argv[2] 這個位置開始。

大檔案拷貝
上邊的程式拷貝一些小檔案沒啥問題,但這種一次性把所有檔案內容都讀取到記憶體中後再一次性寫入磁碟的方式不適合拷貝大檔案,記憶體會爆倉。對於大檔案,我們只能讀一點寫一點,直到完成拷貝。因此上邊的程式需要改造如下。

var fs = require('fs'); function copy(src, dst) { fs.createReadStream(src).pipe(fs.createWriteStream(dst)); } function main(argv) { copy(argv[0], argv[1]); } main(process.argv.slice(2));

以上程式使用 fs.createReadStream 建立了一個原始檔的只讀資料流,並使用 fs.createWriteStream 建立了一個目標檔案的只寫資料流,並且用 pipe 方法把兩個資料流連線了起來。連線起來後發生的事情,說得抽象點的話,水順著水管從一個桶流到了另一個桶。

遍歷目錄

遍歷目錄是操作檔案時的一個常見需求。比如寫一個程式,需要找到並處理指定目錄下的所有JS檔案時,就需要遍歷整個目錄。

遞迴演算法
遍歷目錄時一般使用遞迴演算法,否則就難以編寫出簡潔的程式碼。遞迴演算法與數學歸納法類似,通過不斷縮小問題的規模來解決問題。以下示例說明了這種方法。

function factorial(n) { if(n === 1) { return1; }else { returnn * factorial(n - 1); } }

上邊的函式用於計算 N 的階乘(N!)。可以看到,當 N 大於 1 時,問題簡化為計算 N 乘以 N-1 的階乘。當 N 等於 1 時,問題達到最小規模,不需要再簡化,因此直接返回 1。

陷阱: 使用遞迴演算法編寫的程式碼雖然簡潔,但由於每遞迴一次就產生一次函式呼叫,在需要優先考慮效能時,需要把遞迴演算法轉換為迴圈演算法,以減少函式呼叫次數。

遍歷演算法
目錄是一個樹狀結構,在遍歷時一般使用深度優先+先序遍歷演算法。深度優先,意味著到達一個節點後,首先接著遍歷子節點而不是鄰居節點。先序遍歷,意味著首次到達了某節點就算遍歷完成,而不是最後一次返回某節點才算數。因此使用這種遍歷方式時,下邊這棵樹的遍歷順序是 A > B > D > E > C > F。

A / \ B  C / \  \ D  E  F

同步遍歷
瞭解了必要的演算法後,我們可以簡單地實現以下目錄遍歷函式。

function travel(dir, callback) { fs.readdirSync(dir).forEach(function(file) { varpathname = path.join(dir, file); if(fs.statSync(pathname).isDirectory()) { travel(pathname, callback); }else { callback(pathname); } }); }

可以看到,該函式以某個目錄作為遍歷的起點。遇到一個子目錄時,就先接著遍歷子目錄。遇到一個檔案時,就把檔案的絕對路徑傳給回撥函式。回撥函式拿到檔案路徑後,就可以做各種判斷和處理。因此假設有以下目錄:

- /home/user/ - foo/ x.js - bar/ y.js z.css

使用以下程式碼遍歷該目錄時,得到的輸入如下。

travel('/home/user',function (pathname) { console.log(pathname); });


1 2 3 /home/user/foo/x.js /home/user/bar/y.js /home/user/z.css

非同步遍歷
如果讀取目錄或讀取檔案狀態時使用的是非同步API,目錄遍歷函式實現起來會有些複雜,但原理完全相同。travel函式的非同步版本如下。

function travel(dir, callback, finish) { fs.readdir(dir,function (err, files) { (functionnext(i) { if(i < files.length) { varpathname = path.join(dir, files[i]); fs.stat(pathname,function (err, stats) { if(stats.isDirectory()) { travel(pathname, callback,function () { next(i + 1); }); }else { callback(pathname,function () { next(i + 1); }); } }); }else { finish && finish(); } }(0)); }); }

這裡不詳細介紹非同步遍歷函式的編寫技巧,在後續章節中會詳細介紹這個。總之我們可以看到非同步程式設計還是蠻複雜的。

相關推薦

Node.js本地檔案操作檔案拷貝目錄方法

檔案拷貝NodeJS 提供了基本的檔案操作 API,但是像檔案拷貝這種高階功能就沒有提供,因此我們先拿檔案拷貝程式練手。與 copy 命令類似,我們的程式需要能接受原始檔路徑與目標檔案路徑兩個引數。 小檔案拷貝我們使用 NodeJS 內建的 fs 模組簡單實現這個程式如下。

C語言檔案操作----檔案的讀寫

當檔案按指定的工作方式開啟以後,就可以執行對檔案的讀和寫。下面按檔案的性質分類進行操作。針對文字檔案和二進位制檔案的不同性質,對文字檔案來說,可按字元讀寫或按字串讀寫;對二進位制檔案來說,可進行成塊的讀寫或格式化的讀寫。1. 讀寫字元    C提供fgetc和fputc函式對文字檔案進行字元的讀寫,其函式的原

scala陣列操作Array、ArrayBuffer以及陣列

Array     在Scala中,Array代表的含義與Java中類似,也是長度不可改變的陣列。此外,由於Scala與Java都是執行在JVM中,雙方可以互相呼叫,因此Scala陣列的底層實際上是Java陣列。例如字串陣列在底層就是Java的String[],整數陣

檔案包含目錄

directory traversal(目錄遍歷): 使用者通過這個漏洞,修改url、引數變數,從而讀取web根目錄以外的檔案內容; file include: 開發員的include函式對輸入變數過濾不夠嚴格,導致系統檔案,錯誤包含 一、遠端檔案包含 遠端檔案

檔案上傳下載中的安全問題(上傳漏洞目錄攻擊)

檔案上傳與下載是專案中經常需要提供的功能,不管是哪個web應用幾乎都可以找到.那本屌今天就來說一說我們在開發中的疏忽可能導致的問題. 先建立一個web工程,目錄結構如下  檔案上傳漏洞 我們來看看下面這段檔案上傳程式碼,使用的是common-fileupload.ja

最新Zip壓縮檔案漏洞,黑客可以觸發目錄攻擊

  近日,國內某安全公司研究人員透露了一個關鍵漏洞的詳細資訊,該漏洞影響了許多生態系統中的數千個專案,黑客可以利用這些漏洞在目標系統上實現程式碼執行。  黑客是如何通過Zip壓縮檔案入侵攻擊?被稱為“ZipSlip”的問題是一個任意的檔案覆蓋漏洞,在從檔案檔案中提取檔案時觸發

Node.js讀寫中文內容檔案操作

由於Node.js僅支援如下編碼:utf8, ucs2, ascii, binary, base64, hex,並不支援中文GBK或GB2312之類的編碼,因此如果要讀寫GBK或GB2312格式的檔案的中文內容,必須要用額外的模組:iconv-lite 安裝模組:npm inst

js檔案操作——匯出Excel (js-xlsx)

1. 最簡單的Excel匯出 原理:js可以通過base64或者blob,把一個包含一個<table>的<html>串,匯出成xx.xls格式。而Excel可以開啟html檔案。這樣看起來,就是一個成功的Excel匯出。 var tab

node.js 中的package.json檔案和node_modules的怎麼建立?

轉自:https://www.cnblogs.com/xilego/p/6906601.html package.json檔案可以手工編寫,也可以使用npm init命令自動生成。 $ npm init 這個命令採用互動方式,要求使用者回答一些問題,然後在當前目錄生成一個基本的pack

Android初試--Android中的檔案操作SDcard操作(2)

SDCARD:通俗的說,就像外接硬碟。 在模擬器中使用SDCard,你需要先建立一張SDCard卡(當然不是真的SDCard,只是映象檔案)。建立SDCard可以在Eclipse建立模擬器時隨同建立,也可以使用DOS命令進行建立,在DOS視窗中進入android SDK安裝路徑的tools

Android初試--Android中的檔案操作ROM操作(1)

RAM(Random Access Memory)隨機儲存器,在手機中稱為執行記憶體。通俗的說,就像電腦的記憶體。在斷電以後儲存在上面的資料會自動消失。 ROM(Read-Only Memory)只讀儲存器,存放手機韌體程式碼的儲存器,比如手機的作業系統、一些應用程式如遊戲等。通俗的說,就

Node.js 中fs.access() 判斷檔案目錄是否存在;

var fs = require("fs"); /* -----判斷檔案和目錄是否存在; fs.access(path[, mode], callback); path:判斷的檔名; callback:回撥函式;  */ fs.access("./wenjian.txt",function

C++ 學習筆記——檔案操作檔案

1. 檔案的概念 對於使用者來說,常用到的檔案有兩大類:程式檔案和資料檔案。而根據檔案中資料的組織方式,則可以將檔案分為 ASCII 檔案和二進位制檔案。 ASCII 檔案,又稱字元檔案或者文字檔案,它的每一個位元組放一個 ASCII 程式碼,代表一個字元。 二進位制檔案,又稱內部格式檔案或位元

VS2017檔案操作使用fopen函式總結

fopen中mode引數 r, w, a, r+, w+, a+ 具體區別 r : 只能讀, 必須存在, 可在任意位置讀取 w : 只能寫, 可以不存在, 必會擦掉原有內容從頭寫 a : 只能寫, 可以不存在, 必不能修改原有內容, 只能在結尾追加寫, 檔案指標無效 r+ : 可讀可

node.js中常用的fs檔案系統

fs檔案系統模組對於系統檔案及目錄進行一些讀寫操作。 模組中的方法均有非同步和同步版本,例如讀取檔案內容的函式有非同步的 fs.readFile() 和同步的 fs.readFileSync()。 非同步的方法函式最後一個引數為回撥函式,回撥函式的第一個引數包含了錯誤資訊(error

fortran檔案操作'append'; 'backspace'; 'endfile';

本次內容將講一下檔案操作的“高階技巧!” 例如我要讀取檔案的最後一行資料,一般來說可以直接將前n-1行read過去,再進行讀取 本文將介紹一種新的方法,程式碼如下 program main implicit none integer :: a op

C語言檔案操作fgets()

C語言檔案操作之fgets() 原創  2013年01月25日 11:57:00 標籤: C語言 / fgets... / 檔案操作函式 142460 &

node.js將非同步的讀取檔案目錄改成同步

我們都知道,如果想讀取某一目錄下的檔案時,需使用fs.readdir來進行,看如下程式碼: function getFileList(filePath){ fs.readdir(filePath, (

Linux C高階程式設計——檔案操作庫函式

Linux C高階程式設計——檔案操作之庫函式 宗旨:技術的學習是有限的,分享的精神是無限的 ——為什麼要設計標準I/O庫? 直接使用API進行檔案訪問時,需要考慮許多細節問題 例如:read、write時,緩衝區的大小該如何確定,才能使效率最優 標準I/O庫封裝了諸多

Linux C高階程式設計——檔案操作系統呼叫

Linux C高階程式設計檔案操作之系統呼叫 宗旨:技術的學習是有限的,分享的精神是無限的!         庫函式是一些完成特定功能的函式,一般由某個標準組織製作釋出,並形成一定的標準。使用庫函式編寫的函式一般可以應用於不同的平臺而不需要做任何修改,具有很好的可移植