Как искать уникальную последовательность в двоичных данных?

Я пытаюсь прочитать двоичный файл с заголовком. Я знаю, что определенная информация сохраняется после уникальной последовательности 02 06 08 22 02 02 08 00. Как я могу найти положение такой уникальной последовательности?

я могу использовать

String StreamReadAsText(Поток ScriptObject, Кодировка номера, Количество номеров)

читать двоичный файл один за другим. Но я думаю, что это довольно глупо и медленно.

Кроме того, как я могу сравнить результат от StreamReadAsText(), когда вывод не является фактическим текстом (между 00 и 1F в таблице Ascii)?

Затем, Как мне прочитать двоичный файл как int8 (того же размера, что и символ в строке). Например, читать 02, затем 06, затем 08 и т. Д...

Любая помощь приветствуется и ценится.

С Уважением,

Роджер

2 ответа

Решение

Вы уже на правильном пути, читая файл с помощью потоковых команд. Однако зачем вам читать поток как текст? Вы можете прочитать поток как любое (поддерживаемое) число, используя объект tagGroup в качестве прокси с TagGroupReadTagDataFromStream(),

На самом деле в разделе справки F1 есть пример, где перечислены потоковые команды, которые я здесь просто копирую.

F1 помощь

 Object stream = NewStreamFromBuffer( NewMemoryBuffer( 256 ) )
 TagGroup tg = NewTagGroup();

 Number stream_byte_order = 1; // 1 == bigendian, 2 == littleendian
 Number v_uint32_0, v_uint32_1, v_sint32_0, v_uint16_0, v_uint16_1

 // Create the tags and initialize with default values
 tg.TagGroupSetTagAsUInt32( "UInt32_0", 0 )
 tg.TagGroupSetTagAsUInt32( "UInt32_1", 0 )
 tg.TagGroupSetTagAsLong( "SInt32_0", 0 )
 tg.TagGroupSetTagAsUInt16( "UInt16_0", 0 )
 tg.TagGroupSetTagAsUInt16( "UInt16_1", 0 )

 // Stream the data into the tags   
 TagGroupReadTagDataFromStream( tg, "UInt32_0", stream, stream_byte_order );
 TagGroupReadTagDataFromStream( tg, "UInt32_1", stream, stream_byte_order );
 TagGroupReadTagDataFromStream( tg, "SInt32_0", stream, stream_byte_order );
 TagGroupReadTagDataFromStream( tg, "UInt16_0", stream, stream_byte_order );
 TagGroupReadTagDataFromStream( tg, "UInt16_1", stream, stream_byte_order );

// Show the taggroup, if you want
// tg.TagGroupOpenBrowserWindow("AuxTags",0)

 // Get the data from the tags
 tg.TagGroupGetTagAsUInt32( "UInt32_0", v_uint32_0 )
 tg.TagGroupGetTagAsUInt32( "UInt32_1", v_uint32_1 )
 tg.TagGroupGetTagAsLong( "Sint32_0", v_sint32_0 )
 tg.TagGroupGetTagAsUInt16( "UInt16_0", v_uint16_0 )
 tg.TagGroupGetTagAsUInt16( "UInt16_1", v_uint16_1 )

На сайте уже есть пост о поиске шаблона в потоке: Найти изображение шаблона (двоичный файл). Здесь показано, как вы можете использовать поток для просмотра изображения, но вы, конечно же, можете напрямую использовать файловый поток.


В качестве альтернативы вы можете прочитать весь массив из потока с помощью ImageReadImageDataFromStream после подготовки подходящего изображения заранее. Затем вы можете использовать изображения для поиска местоположения. Это будет пример:

// Example of reading the first X bytes of a file
// as uInt16 data

image ReadHeaderAsUint16( string filepath, number nBytes )
{
    number kEndianness = 0 // Default byte order of the current platform
    if ( !DoesFileExist( filePath ) ) 
        Throw( "File '" + filePath + "' not found." )
    number fileID = OpenFileForReading( filePath )
    object fStream = NewStreamFromFileReference( fileID, 1 )
    if ( nBytes > fStream.StreamGetSize() ) 
        Throw( "File '" + filePath + "' has less than " + nBytes + "bytes." )

    image buff := IntegerImage( "Header", 2, 0, nBytes/2 )  // UINT16 array of suitable size
    ImageReadImageDataFromStream( buff, fStream, kEndianness )
    return buff 
}

number FindSignature( image header, image search )
{
    // 1D images only
    if (        ( header.ImageGetNumDimensions() != 1 ) \
            ||  ( search.ImageGetNumDimensions() != 1 ) )
        Throw( "Only 1D images supported" )

    number sx = search.ImageGetDimensionSize( 0 ) 
    number hx = header.ImageGetDimensionSize( 0 )
    if ( hx < sx )
        return -1

    // Create a mask of possible start locations
    number startV = search.getPixel( 0, 0 )
    image mask = (header == startV) ? 1 : 0

    // Search all the occurances from the first
    number mx, my
    while( max( mask, mx, my ) )
    {
        if ( 0 == sum( header[0,mx,1,mx+sx] - search ) )
            return mx
        else
            mask.SetPixel( mx, 0, 0)
    }
    return -1
}

// Example
// 1) Load file header as image (up to the size you want )
string path = GetApplicationDirectory( "open_save", 0 )
number maxHeaderSize = 200
if ( !OpenDialog( NULL, "Select file to open", path, path ) ) Exit(0)
image headerImg := ReadHeaderAsUint16( path, maxHeaderSize  )
headerImg.ShowImage()

// 2) define search-header as image
image search := [8]: { 02, 06, 08, 22, 02, 02, 08, 00 }
// MatrixPrint( search )

// 3) search for it in the header
number foundAt = FindSignature( headerImg, search )
if ( -1 == foundAt ) 
    Throw( "The file header does not contain the search pattern." )
else
    OKDialog( "Found the search pattern at offset: " + foundAt * 16 + "bytes" )

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

Это не самый эффективный способ памяти или даже самый быстрый способ, но он достаточно простой и быстрый, если у вас есть ресурсы для записи.

Другие вопросы по тегам