Как искать уникальную последовательность в двоичных данных?
Я пытаюсь прочитать двоичный файл с заголовком. Я знаю, что определенная информация сохраняется после уникальной последовательности 02 06 08 22 02 02 08 00. Как я могу найти положение такой уникальной последовательности?
я могу использовать
String StreamReadAsText(Поток ScriptObject, Кодировка номера, Количество номеров)
читать двоичный файл один за другим. Но я думаю, что это довольно глупо и медленно.
Кроме того, как я могу сравнить результат от StreamReadAsText(), когда вывод не является фактическим текстом (между 00 и 1F в таблице Ascii)?
Затем, Как мне прочитать двоичный файл как int8 (того же размера, что и символ в строке). Например, читать 02, затем 06, затем 08 и т. Д...
Любая помощь приветствуется и ценится.
С Уважением,
Роджер
2 ответа
Вы уже на правильном пути, читая файл с помощью потоковых команд. Однако зачем вам читать поток как текст? Вы можете прочитать поток как любое (поддерживаемое) число, используя объект tagGroup в качестве прокси с TagGroupReadTagDataFromStream()
,
На самом деле в разделе справки 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" )
Если вы работаете на современном компьютере, просто загрузите файл в память, а затем отсканируйте последовательность, используя функцию сравнения памяти и путевой индекс.
Это не самый эффективный способ памяти или даже самый быстрый способ, но он достаточно простой и быстрый, если у вас есть ресурсы для записи.