2014-02-26 63 views
0

我有一個二進制格式的文件:NodeJS:如何使用readStream編寫文件解析器?

格式如下:

[4 - header bytes] [8 bytes - int64 - how many bytes to read following] [variable num of bytes (size of the int64) - read the actual information]

然後它重複,所以我必須首先讀取前12個字節,以確定有多少更多的字節我需要閱讀。

我曾嘗試:

var readStream = fs.createReadStream('/path/to/file.bin'); 
readStream.on('data', function(chunk) { ... }) 

我的問題是,該塊總是回來在65536個字節塊在同一時間,而我需要的,我讀的字節數更加具體。

我一直試圖readStream.on('readable', function() { readStream.read(4) }) 但它也並不是很靈活,因爲它似乎變成異步代碼爲同步代碼,因爲,我必須把「讀書」在while循環

也許readStream是不適合在這種情況下,我應該用這個呢? fs.read(fd, buffer, offset, length, position, callback)

回答

0

這裏是我建議的readStream的抽象處理程序處理抽象數據像你描述:

var pending = new Buffer(9999999); 
var cursor = 0; 
stream.on('data', function(d) { 
    d.copy(pending, cursor); 
    cursor += d.length; 

    var test = attemptToParse(pending.slice(0, cursor)); 
    while (test !== false) { 
    // test is a valid blob of data 
    processTheThing(test); 

    var rawSize = test.raw.length; // How many bytes of data did the blob actually take up? 
    pending.copy(pending.copy, 0, rawSize, cursor); // Copy the data after the valid blob to the beginning of the pending buffer 
    cursor -= rawSize; 
    test = attemptToParse(pending.slice(0, cursor)); // Is there more than one valid blob of data in this chunk? Keep processing if so 
    } 
}); 

爲您的使用情況,確保pending的初始化大小緩衝區足夠大以容納您將要解析的最大可能有效數據塊(您提到一個int64;最大大小加上頭大小),再加上一個額外的65536個字節,以防止塊邊界恰好在流的邊緣發生塊。

我的方法需要attemptToParse()方法,它採用一個緩衝器,並試圖解析該數據在它外面。如果緩衝區的長度太短(數據還不夠),它應該返回false。如果它是一個有效的對象,它應該返回一些解析的對象,以便顯示它佔用的原始字節(在我的示例中爲.raw屬性)。然後,你需要做任何處理你需要做的blob(processTheThing()),修剪出有效的blob數據,將待處理的Buffer移到剩下的部分並繼續。這樣,你就沒有一個不斷增長的pending緩衝區,或者一些「完成的」blob陣列。也許對processTheThing()接收端過程中保持斑點的陣列中的存儲,也許是他們寫入數據庫,但在這個例子裏,是抽象化了所以這段代碼只是如何處理數據流的交易。

+0

有趣的是,即使我們的代碼做了非常類似的事情(在緩衝區中收集數據塊),代碼和方法調用也完全不同。例如'd.copy()'和'Buffer.concat()'。 – user949300

+0

正確;我避免了'Buffer.concat()',因爲在這種情況下,不需要處理數組和緩衝區;將增長後的Buffer包裝在一個數組中只是增加了一些開銷,而且'concat()'方法表示如果沒有給出長度,它必須遍歷緩衝區兩次,所以可能使用'copy()'方法,指針保持你的位置是更好的性能方法,雖然我沒有檢查確定。 – MidnightLightning

0

塊添加到緩衝區中,然後從那裏分析數據。意識到不要超出緩衝區的末端(如果數據很大)。我現在正在使用我的平板電腦,因此無法添加任何示例源代碼。也許別人可以?

好了,小源,非常骨骼。

var chunks = []; 
var bytesRead= 0; 

stream.on('data', function(chunk) { 

    chunks.push(chunk); 
    bytesRead += chunk.length; 

    // look at bytesRead... 
    var buffer = Buffer.concat(chunks); 
    chunks = [buffer]; // trick for next event 
     // --> or, if memory is an issue, remove completed data from the beginning of chunks 
    // work with the buffer here... 

} 
+0

如何將塊添加到緩衝區?我是否需要在某處保留一個緩衝區變量並等待下一個數據事件?例如例如,如果我需要讀取12個字節,然後發現需要讀取100k字節並且塊長度爲60k,是否需要等待下一個數據事件將其附加到緩衝區。 – samol

+0

查看編輯答案。是的,如果數據爲100k,則必須等待更多數據事件。希望能讓你開始 – user949300

+0

,所以塊將會不斷增長到一個巨大的數組? – samol