parsing一个stream而不削减

我正在阅读一个stream,这是testing与正则expression式:

var deviceReadStream = fs.createReadStream("/path/to/stream"); deviceReadStream.on('data',function(data){ if( data.match(aRegex) ) //do something }); 

但是由于河stream被分成几个大块,所以切入可能会让我错过一场比赛。 所以有一个更好的模式来连续testing一个正则expression式的stream?

更多细节

stream是崩溃的文件系统的内容。 我正在寻找一个ext2签名(0xef53)。 由于我不知道块是如何分裂的,签名可能被分割而不被检测到。

所以我使用了一个循环来自定义块的分割方式,即通过文件系统的块来分割。

但使用stream似乎是一个更好的模式,所以如何使用stream,同时定义自己的块大小?

首先,如果您决定使用nodejs的正则expression式,请尝试一下。 pcre的节点包装器可用。 Pcre可以configuration为进行部分匹配,可以跨缓冲区边界恢复。

但是,您可能只需要grep (或多个静态string的fgrep )从terminal的字节偏移量。 然后,您可以使用xxdless xxd来查看它,或者使用dd来提取一部分。

例如,要获得与grep的偏移量:

 grep --text --byte-offset --only-matching --perl-regex "\xef\x53" recovery.img 

请注意,grep命令行选项可能因发行版而异。

你也可以看看bgrep,虽然我没有用过。

我已经运用各种shell工具和脚本进行恢复。

一些其他的切线评论:

  1. 请记住你正在search的任何内容。
  2. 如果您还没有做过恢复,请拍照。 除此之外,如果设备开始出现故障,进一步的访问可能会使情况变得更糟。
  3. 参考资料雕刻工具。 REF
  4. 正如你所提到的,文件可能被分割。 我仍然期望分区和文件从扇区边界开始。 据我所知,魔法通常不会被分割。
  5. 小心不要无意中写入正在恢复的设备。
  6. 正如你可能知道的,如果你重build的图像,你可能能够使用环回驱动程序安装图像。

假设您的代码只需要search签名0xef53(如在您的问题的“更多细节”部分中指定的…

一种方法做到这一点,并继续使用正则expression式是保持前一个数据缓冲区的引用,连接到当前的数据缓冲区,并运行正则expression式。 由于它有效地扫描每个数据缓冲区两次(因为串联存在大量内存分配),所以它的CPU使用率有点高。 阅读起来比较容易,所以将来可以维护。

下面是代码的例子

 var deviceReadStream = fs.createReadStream("/path/to/stream"); var prevData = ''; deviceReadStream.on('data',function(data){ var buffer = prevData + data; if( buffer.match(aRegex) ) //do something prevData = data; }); 

另一种select是更多地手动进行字符比较,以便在签名分散到数据缓冲区时可以捕获代码。 你可以看到在这个相关的问题的解决scheme有效的方式来search一个string的stream 。 根据顶级答案的博客文章,他编写的Haxe代码可以用来生成JavaScript,然后可以使用它。 或者您可以编写自己的自定义代码来执行search,因为您要查找的签名只有4个字符。

我会把数据stream视为一个大小为6字节的移动窗口。

例如,如果您有以下文件(以字节为单位): 23, 34, 45, 67, 76

传递数据的移动窗口将是:

 [23, 34] [34, 45] [45, 67] [67, 76] 

我build议通过这些窗口寻找你的string。

 var Stream = require('stream'); var fs = require('fs'); var exampleStream = fs.createReadStream("./dump.dmp"); var matchCounter = 0; windowStream(exampleStream, 6).on('window', function(buffer){ if (buffer.toString() === '0xEF53') { ++matchCounter; } }).on('end', function(){ console.log('done scanning the file, found', matchCounter); }); function windowStream(inputStream, windowSize) { var outStream = new Stream(); var soFar = []; inputStream.on('data', function(data){ Array.prototype.slice.call(data).forEach(function(byte){ soFar.push(byte); if (soFar.length === windowSize) { outStream.emit('window', new Buffer(soFar)); soFar.shift(); } }); }); inputStream.on('end', function(){ outStream.emit('end'); }); return outStream; } 

通常情况下,当你真的需要下划线的string时,我不是一个超越字节的粉丝。 在UTF-8中,有些情况下可能会导致一些问题,但假设一切都是英文的,应该没问题。 该示例可以通过使用string解码器来改进以支持这些情况

编辑

这是一个UTF8版本

 var Stream = require('stream'); var fs = require('fs'); var exampleStream = fs.createReadStream("./dump.dmp", {encoding: 'utf8'}); var matchCounter = 0; windowStream(exampleStream, 6).on('window', function(windowStr){ if (windowStr === '0xEF53') { ++matchCounter; } }).on('end', function(){ console.log('done scanning the file, found', matchCounter); }); function windowStream(inputStream, windowSize) { var outStream = new Stream(); var soFar = ""; inputStream.on('data', function(data){ Array.prototype.slice.call(data).forEach(function(char){ soFar += char; if (soFar.length === windowSize) { outStream.emit('window', soFar); soFar = soFar.slice(1); } }); }); inputStream.on('end', function(){ outStream.emit('end'); }); return outStream; }