Подтвердить что ты не робот

Разбор потока без обрезки

Я читаю поток, который проверяется с помощью регулярного выражения:

var deviceReadStream = fs.createReadStream("/path/to/stream");

deviceReadStream.on('data',function(data){
  if( data.match(aRegex) )
    //do something
});

Но поскольку поток разделен на несколько кусков, возможно, что разрез заставит меня пропустить матч. Итак, есть лучший образец для непрерывного тестирования потока с регулярным выражением?

подробнее

Поток представляет собой содержимое файловой системы . Я ищу подпись ext2 (0xef53). Поскольку я не знаю, как расщепляются куски, подпись может быть разделена и не обнаружена.

Итак, я использовал цикл, чтобы иметь возможность ограничивать себя тем, как расщепляются куски, т.е. блоком файловой системы.

Но использование потоков кажется лучшим образцом, поэтому как я могу использовать потоки, определяя размер кусков?

4b9b3361

Ответ 1

Во-первых, если вы решили использовать регулярное выражение с nodejs, попробуйте pcre. Доступен node wrapper для pcre. Pcre может быть настроен на частичные совпадения, которые могут возобновляться через границы буфера.

Вы можете, однако, просто grep (или fgrep для нескольких статических строк) для смещения байта от терминала. Затем вы можете просмотреть его с помощью xxd и less, чтобы просмотреть его, или dd, чтобы извлечь часть.

Например, чтобы получить смещения с помощью grep:

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

Обратите внимание, что параметры командной строки grep могут различаться в зависимости от вашего дистрибутива.

Вы также можете посмотреть bgrep, хотя я его не использовал.

Мне посчастливилось сделать восстановление с помощью различных инструментов оболочки и скриптов.

Несколько других тангенциальных комментариев:

  • Помните о том, что вы ищете.
  • Возьмите изображение, так как вы делаете восстановление, если вы еще этого не сделали. Среди других опасностей, если устройство начинает терпеть неудачу, дальнейший доступ может ухудшить его.
  • Справочные инструменты для резки данных. ref
  • Как вы упомянули, файлы могут быть фрагментированы. Тем не менее я бы ожидал, что разделы и файлы начнутся с границ сектора. Насколько я знаю, магия обычно не разделялась.
  • Будьте осторожны, чтобы случайно не записать на устройство, которое вы восстанавливаете.
  • Как вы знаете, если вы восстановите изображение, вы сможете смонтировать изображение с помощью шлейф-драйвера.

Ответ 2

Предполагая, что вашему коду просто нужно найти подпись 0xef53 (как указано в части "подробнее" вашего вопроса...

Один из способов сделать это и продолжать использовать регулярное выражение - сохранить ссылку на предыдущий буфер данных, объединить его с текущим буфером данных и запустить регулярное выражение. Это немного тяжело для использования процессора, поскольку он эффективно сканирует каждый буфер данных дважды (и там много выделения памяти из-за конкатенации). Это относительно легко читать, поэтому его следует поддерживать в будущем.

Вот пример того, как будет выглядеть код

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;
});

Другим вариантом было бы более ручное сравнение символов, чтобы код мог поймать, когда подпись разбита на буферы данных. Вы можете увидеть решение этого вопроса по этому вопросу Эффективный способ поиска потока для строки. Согласно сообщению в блоге верхнего ответа, код Haxe, который он написал, может быть создан для создания JavaScript, который вы затем можете использовать. Или вы можете написать свой собственный код для выполнения поиска, так как подпись, которую вы ищете, имеет длину всего 4 символа.

Ответ 3

Я бы посмотрел на поток данных в виде движущегося окна размером 6 байт.

Например, если у вас есть следующий файл (в байтах): 23, 34, 45, 67, 76

Движущееся окно 2, проходящее через данные, будет:

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

Я предлагаю перебирать эти окна в поисках вашей строки.

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;
}

Обычно я не поклонник перебора байтов, когда вам действительно нужна строка underling. В UTF-8 есть случаи, когда это может вызвать некоторые проблемы, но при условии, что все на английском языке, все должно быть хорошо. Пример может быть улучшен для поддержки этих случаев с помощью строкового декодера

ИЗМЕНИТЬ

Вот версия 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;
}