2017-06-15 1 views
1

J'essaye de lire un dossier binaire avec l'en-tête. Je sais que certaines informations sont sauvegardées après une séquence unique 02 06 08 22 02 02 08 00. Comment pourrais-je trouver la position d'une telle séquence unique?Comment rechercher une séquence unique dans les données binaires?

Je peux utiliser

Chaîne StreamReadAsText (comptage flux ScriptObject, encodage Nombre, Nombre)

pour lire le fichier binaire un par un. Mais je suppose que c'est assez bête et lent. En outre, comment puis-je comparer le résultat de StreamReadAsText() lorsque la sortie n'est pas un texte réel (entre 00 et 1F dans la table Ascii)?

Alors, comment puis-je lire le fichier binaire comme int8 (la même taille comme un caractère dans une chaîne) .Par exemple, lu 02, puis 06, puis 08 etc ...

Toute aide est la bienvenue et apprécié.

Cordialement,

Roger

+0

connexes (mais pas en double): https://stackoverflow.com/q/34834197/1302888 – BmyGuest

Répondre

1

Vous êtes déjà sur la bonne voie en lisant le fichier avec les commandes de diffusion. Cependant, pourquoi voudriez-vous lire le flux en tant que texte? Vous pouvez lire le flux en tant que n'importe quel numéro (pris en charge), en utilisant l'objet tagGroup en tant que proxy avec TagGroupReadTagDataFromStream().

Il existe en fait un exemple dans la section d'aide F1 où les commandes de diffusion sont listées, que je suis en train de copier ici.

F1 help

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) 

Il y a déjà un poste ici sur place sur la recherche d'un modèle dans un cours d'eau: Find a pattern image (binary file) Cela montre comment vous pouvez utiliser un flux de regarder dans une image, mais vous pouvez utiliser le FileStream directement bien sûr.


Comme alternative, vous pouvez lire un tableau entier du flux avec ImageReadImageDataFromStream après la préparation d'une image appropriée au préalable. Vous pouvez ensuite utiliser des images pour rechercher un lieu. Ce serait un exemple:

// 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") 
+0

Merci pour votre réponse. – Roger

+0

Merci pour votre réponse. Je ne suis pas très familier avec les tags. Mais je suis capable de lire le flux par tags comme Int32, Int16 et Double. À ma compréhension, Int32 a la longueur comme 02 06 08 22, tandis que Int16 a la longueur comme 02 06. Le flux vient comme 00 02 06 08, alors il manquera cette séquence en lisant Int16. Donc je vais devoir lire "Int8" (je ne sais même pas si ça s'appelle de cette façon). Alors la longueur devrait seulement être comme 02.De cette façon, je serai sûr qu'il ne manquera pas la bonne séquence d'en-tête. Le problème en ce moment est que je ne peux pas lire "Int8". Seul le flux de lecture en tant que texte a une telle longueur, mais je peux comparer ASCII – Roger

+0

@Roger Vous pouvez lire les données comme UInt8 image - IntegerImage ("", 1,0, ...) - ou Int8 image - IntegerImage ("", 1 , 1, ...). Ou vous pouvez rechercher avec deux passes (une avec un décalage de 1 octet par étape). Malheureusement, je ne connais pas de commande "GetTagAsUInt8" ou "Int8" en ce moment. – BmyGuest

0

Si vous êtes sur une machine moderne, il suffit de charger le fichier dans la mémoire, puis rechercher automatiquement la séquence en utilisant une fonction de comparaison de mémoire et un indice de voyage. Ce n'est pas la manière la plus efficace de faire de la mémoire ou même la plus rapide, mais c'est assez simple et rapide, en supposant que vous ayez des ressources à graver.

+0

ne sert malheureusement il n'y a pas funciton availaible dans le langage script DM. Cependant, l'idée que j'ai postée ci-dessous n'est pas très différente en principe. – BmyGuest