2012-11-02 66 views
3

我需要打開一個包含文件的目錄..爲每個文件打開readstream並將所有文件中的數據寫入單個文件。但我不斷收到錯誤:EMFILE,打開'塊/ piece96.data'Nodejs錯誤:EMFILE

我的ulimit是256,我增加到1024.

我的代碼如下



    var DIR='chunks/'; 
    var files=fs.readdirSync(DIR); 
    var filename='bach.mp3'; 

    files.forEach(function(singlebit){ 
     //console.log(files); 
     var bit=fs.createReadStream(DIR+singlebit); 
     var resultfile=fs.createWriteStream(filename,{ 
      flags:'r+', 
      encoding:null, 
      mode:0666 
     }); 
     bit.on('data',function(bitdata){ 
       resultfile.write(bitdata); 
       console.log(bitdata); 
      }).on('end',function(){ 
       resultfile.end(); 
      }); 
     }); 
    console.log('file complete'); 

我怎樣才能防止EMI文件錯誤。由於我正在使用readdirSync並且不是一次打開所有文件,因此我一次不打開多個文件。我需要一種方法來讀取所有文件並寫入單個文件。

+1

你.forEach爲每個文件創建一個功能在你的目錄中。您對每個文件至少使用2個文件句柄,以及下面使用的任何節點。無論如何,有了這麼多的文件,你可能想要限制你的並發動作,使用'async' ... – Joe

+1

我改變了寫入流同步。這解決了它。 –

+0

@GokulKav你拯救了我的一天。謝謝! – shaosh

回答

3

我剛寫完的一小段代碼來解決這個問題我自己,我不使用流,但是這應該是適應您的需求:

// Queuing reads and writes, so your nodejs script doesn't overwhelm system limits catastrophically 
global.maxFilesInFlight = 100; // Set this value to some number safeish for your system 
var origRead = fs.readFile; 
var origWrite = fs.writeFile; 

var activeCount = 0; 
var pending = []; 

var wrapCallback = function(cb){ 
    return function(){ 
     activeCount--; 
     cb.apply(this,Array.prototype.slice.call(arguments)); 
     if (activeCount < global.maxFilesInFlight && pending.length){ 
      console.log("Processing Pending read/write"); 
      pending.shift()(); 
     } 
    }; 
}; 
fs.readFile = function(){ 
    var args = Array.prototype.slice.call(arguments); 
    if (activeCount < global.maxFilesInFlight){ 
     if (args[1] instanceof Function){ 
      args[1] = wrapCallback(args[1]); 
     } else if (args[2] instanceof Function) { 
      args[2] = wrapCallback(args[2]); 
     } 
     activeCount++; 
     origRead.apply(fs,args); 
    } else { 
     console.log("Delaying read:",args[0]); 
     pending.push(function(){ 
      fs.readFile.apply(fs,args); 
     }); 
    } 
}; 

fs.writeFile = function(){ 
    var args = Array.prototype.slice.call(arguments); 
    if (activeCount < global.maxFilesInFlight){ 
     if (args[1] instanceof Function){ 
      args[1] = wrapCallback(args[1]); 
     } else if (args[2] instanceof Function) { 
      args[2] = wrapCallback(args[2]); 
     } 
     activeCount++; 
     origWrite.apply(fs,args); 
    } else { 
     console.log("Delaying write:",args[0]); 
     pending.push(function(){ 
      fs.writeFile.apply(fs,args); 
     }); 
    } 
}; 
+0

這個錯誤爲什麼會發生?有沒有更簡單的方法呢? – yas4891

+2

每個操作系統都會限制任意進程可以同時打開的文件句柄的數量。 OSX將默認限制降低了一點,但真正的情況是nodejs使得堆疊很多並行操作變得非常容易。當你有簡單的邏輯來遍歷目錄樹並簡單地處理所有文件時,實際上你的代碼比磁盤I/O時間花費的時間少得多,並且非常快速地達到這個限制。實際上,如果您處理音樂庫,您不到一秒鐘就會告訴操作系統打開數千個文件,將所有內容融合在一起。 – fbartho