2017-06-15 2 views
1

ヘッダー付きのバイナリファイルを読み込もうとしています。ユニークなシーケンスの後に特定の情報が保存されていることを知っています02 06 08 22 02 02 08 00。このようなユニークなシーケンスの位置をどのように見つけることができますか?バイナリデータで一意のシーケンスを検索する方法は?

私は、バイナリファイルを一つずつ読むために

文字列StreamReadAsText(スクリプトオブジェクトストリーム、番号のエンコード、数カウント)

を使用することができます。しかし、私はそれがかなりばかげて遅いと思います。

さらに、出力が実際のテキスト(Asciiテーブルの00と1Fの間)でない場合、StreamReadAsText()の結果をどのように比較すればよいですか?その後

は、私が例.FOR INT8としてバイナリファイル(文字列の文字と同じ大きさ)を読むにはどうすればよい、

すべてのヘルプは大歓迎です...その後、08などを、その後02、06を読んで感謝します。

よろしく、

ロジャー

+0

関連(ただし、重複しない):これは一例になりhttps://stackoverflow.com/q/34834197/1302888 – BmyGuest

答えて

1

ストリーミングコマンドを使用してファイルを読むと、適切なトラックに既に入っています。しかし、なぜストリームをテキストとして読みたいのでしょうか? のプロキシとしてtagGroupオブジェクトを使用して、任意の(サポートされている)番号としてストリームを読み取ることができます。

実際にF1ヘルプセクションには、ストリーミングコマンドがリストされていますが、ここではコピーしています。

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) 

ストリーム内のパターンを検索に関するサイト上のここでの投稿はすでにあります:Find a pattern image (binary file) これはあなたがイメージで見えるようにストリームを使用する方法を示していますが、使用することができますもちろん直接ファイルストリーム。代替として


は、事前に適切な画像を作成した後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") 
+0

返信ありがとうございます。 – Roger

+0

お返事ありがとうございます。私はタグに慣れていません。しかし、私はInt32、Int16、Doubleのようにタグでストリームを読むことができます。私の理解では、Int32は02 06 08 22のような長さを持ち、Int16は02 06のような長さを持っています。ストリームは00 02 06 08のようになり、Int16を読むことでこのシーケンスを逃します。だから私は "Int8"と読む必要があります(私はそれがこのように呼ばれているかどうかわかりません)。その後、長さは02のようにする必要があります。このようにして、私はそれが正しいヘッダーシーケンスを欠場しないことを確かめるでしょう。今の問題は「Int8」を読むことができないことです。このような長さのテキストを読み取るだけですが、私はASCIIを比較することができます – Roger

+0

@RogerあなたはUInt8イメージとしてデータを読むことができます - IntegerImage( ""、1,0、...) - またはInt8イメージ - IntegerImage( ""、1 、1、...)。または、2つのパス(ステップごとに1バイトのオフセットを持つパス)で検索することもできます。残念ながら、私は今すぐ "GetTagAsUInt8"や "Int8"のようなコマンドを知りません。 – BmyGuest

0

あなたは、現代のマシンにしている場合は、単に、メモリ比較機能と走行インデックスを使用してシーケンスをスキャンし、ファイルをメモリにロードします。

これは、メモリを最も効率的に使用する方法ではなく、最も高速ですが、簡単に作成することができます。

+0

Unfortuanately DM-スクリプト言語には、このようなfuncitonのavailaibleはありません。しかし、私が下に投稿したアイデアは、原則ではあまり違いはありません。 – BmyGuest

関連する問題