線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1074
推到 Plurk!
推到 Facebook!

如何取出TMemoryStream的片段並比較呢?

尚未結案
chtai
高階會員


發表:68
回覆:238
積分:116
註冊:2004-05-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-05-30 03:03:07 IP:140.113.xxx.xxx 未訂閱
我的問題是這樣的,目前我想要寫個簡單分析midi檔的程式 之前有好心人建議我可以先把midi檔讀進TMemoryStream裡再處理 可以減少許多 I/O 的動作.  而且TMemoryStream裡的東東就是一個個BYTE了,拿來分析也比較方便.
可是現在問題來了,midi檔裡頭有分許多的小部分(chunk), 而每個部分的檔頭不太一樣,我必須依據檔頭來決定要怎麼分析這一部分. 檔頭看起來如下: 4D 54 68 64 00 00 00 06 ff ff nn nn dd dd ----這是第一種 4D 54 72 6B xx xx xx xx ----這是第二種
在第一種裡,是由4D546864 (ASCII的 Mthd )開頭 在第二種裡,是由4D54726B (ASCEE的 Mtrk )開頭 我要怎麼做才能取出一個片段(例如:開頭的4個Byte) 並比較它是等於某一字串(例如 Mthd 或是 Mtrk )呢?
搜尋了站上的文章,似乎都只提到怎麼對一個Byte或Word處理, 而沒提到要如何處理一個片段哩~ (若是只能一個個Byte比對,那光是比對一個檔頭就要好幾層的 if 耶 @@) 還請大家教導小弟了~~
------
My Web: http://nelson.csie.us
My Blog: http://blog.nelson.csie.us
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-05-30 10:50:00 IP:203.204.xxx.xxx 未訂閱
如果您的資料是 4 bytes 為單位,可以直接把它變成 int 或 unsigned int 的陣列,例如:
unsigned int *Buf=(unsigned int *)Stream->Memory;
int DataCount=Stream->Size/4;
for(int i=0;i
如果資料不是 4 bytes 為單位,只能以 1 byte 1 byte 為單位,那就用
unsigned char *Buf=(unsigned char *)Stream->Memory;
unsigned int *Data;
for(int i=0;iSize-3;i  )
{
  Data=(unsigned int*)&Buf[i];
  if(*Data==0x6468544D) // 4D 54 68 64
  {
    // 記錄 Offset 或直接對 Buf[i N] 的資料作處理,
    // 處理完,再把 i=i N 如此,再下一個 for loop 
    // 處理時,就不會重覆判斷了。
  }
}
或是
unsigned char *Buf=(unsigned char *)Stream->Memory;
for(int i=0;iSize-3;i  )
{
  if(Buf[i 0]==0x4D  // 4D 54 68 64
  && Buf[i 1]==0x54
  && Buf[i 2]==0x68
  && Buf[i 3]==0x64)
  {
    // 記錄 Offset 或直接對 Buf[i N] 的資料作處理,
    // 處理完,再把 i=i N 如此,再下一個 for loop 
    // 處理時,就不會重覆判斷了。
  }
}
這樣就不會有多層的 if 了。 http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
chtai
高階會員


發表:68
回覆:238
積分:116
註冊:2004-05-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-05-30 11:39:22 IP:140.113.xxx.xxx 未訂閱
太感謝dllee大哥了 我想再請問的是,若我有一段 xx,或是 xx xx 或是 xx xx xx (即1 BYTE, 2 BYTE, 3BYTE, 或是更多不定個BYTE) (不一定是由幾個BYTE組成,但是我知道是幾個BYTE.) 現在這一段BYTE代表的是一個數字的話, 我應該怎麼做才能把這一段轉成一個十進位的數字呢?
------
My Web: http://nelson.csie.us
My Blog: http://blog.nelson.csie.us
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-05-30 20:57:23 IP:211.76.xxx.xxx 未訂閱
unsigned char *Buf=(unsigned char *)Stream->Memory;    // 1 byte:
Label1->Caption=AnsiString(Buf[i]);    // 2 bytes:
unsigned short *usData=(unsigned short *)&Buf[i];
Label1->Caption=AnsiString(*usData);    // 4 bytes:
unsigned int *uiData=(unsigned int *)&Buf[i];
Label1->Caption=AnsiString(*uiData);    // 其他特殊的 bytes 組合: (以 3 bytes 為例)
unsigned int Data=Buf[i 0]
                  Buf[i 1]<<8
                  Buf[i 2]<<16;
Label1->Caption=AnsiString(Data);    // 以上是假設 [i 0] 是低位元組,[i 2] 是高位元組,如果高低相反,則
unsigned int Data=Buf[i 2]
                  Buf[i 1]<<8
                  Buf[i 0]<<16;
Label1->Caption=AnsiString(Data);
最後,關於 10 進位... 其實,存在電腦內的都是 2 進位,但電腦語言都會提供轉成人看的 10 進位函式。像一般的 int 變數,它存在記憶體內當然是 2 進位的型式,而需要轉出來看時,用 IntToStr() 就可以看到其 10 進位的數值。在使用 BCB 時,AnsiString 的功能算是很強的,幾乎把任何東西丟給它,它都可以轉換,再找個 Label 或是放入 ListBox,Memo 來看都行。 http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc. 發表人 - dllee 於 2004/05/30 20:58:17
------
http://www.ViewMove.com
chtai
高階會員


發表:68
回覆:238
積分:116
註冊:2004-05-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-06-01 01:49:11 IP:140.113.xxx.xxx 未訂閱
感謝dllee大哥 我會再試看看的. 到時有問題再麻煩大家了
------
My Web: http://nelson.csie.us
My Blog: http://blog.nelson.csie.us
aquarius
資深會員


發表:3
回覆:347
積分:330
註冊:2003-05-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-06-01 11:44:29 IP:211.23.xxx.xxx 未訂閱
    不用這麼麻煩吧!! 用 CompareMem 就可以比較兩段 Memory 的內容了!!    
引言:
unsigned char *Buf=(unsigned char *)Stream->Memory;    // 1 byte:
Label1->Caption=AnsiString(Buf[i]);    // 2 bytes:
unsigned short *usData=(unsigned short *)&Buf[i];
Label1->Caption=AnsiString(*usData);    // 4 bytes:
unsigned int *uiData=(unsigned int *)&Buf[i];
Label1->Caption=AnsiString(*uiData);    // 其他特殊的 bytes 組合: (以 3 bytes 為例)
unsigned int Data=Buf[i 0]
                  Buf[i 1]<<8
                  Buf[i 2]<<16;
Label1->Caption=AnsiString(Data);    // 以上是假設 [i 0] 是低位元組,[i 2] 是高位元組,如果高低相反,則
unsigned int Data=Buf[i 2]
                  Buf[i 1]<<8
                  Buf[i 0]<<16;
Label1->Caption=AnsiString(Data);
最後,關於 10 進位... 其實,存在電腦內的都是 2 進位,但電腦語言都會提供轉成人看的 10 進位函式。像一般的 int 變數,它存在記憶體內當然是 2 進位的型式,而需要轉出來看時,用 IntToStr() 就可以看到其 10 進位的數值。在使用 BCB 時,AnsiString 的功能算是很強的,幾乎把任何東西丟給它,它都可以轉換,再找個 Label 或是放入 ListBox,Memo 來看都行。 http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc. 發表人 - dllee 於 2004/05/30 20:58:17
...Aquarius
------
水瓶男的blog: http://791909.blogspot.com
chtai
高階會員


發表:68
回覆:238
積分:116
註冊:2004-05-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-06-01 20:24:00 IP:140.113.xxx.xxx 未訂閱
引言: 不用這麼麻煩吧!! 用 CompareMem 就可以比較兩段 Memory 的內容了!! ...Aquarius
Aquarius兄您好: 小弟不曾用過這個函式哩~ 不知您是否願意就這個例子說明一下要如何使用呢? -- chtai
------
My Web: http://nelson.csie.us
My Blog: http://blog.nelson.csie.us
aquarius
資深會員


發表:3
回覆:347
積分:330
註冊:2003-05-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-06-03 16:54:48 IP:210.243.xxx.xxx 未訂閱
引言: Aquarius兄您好: 小弟不曾用過這個函式哩~ 不知您是否願意就這個例子說明一下要如何使用呢?
很簡單使用呀!! 請看 HELP Performs a binary comparison of two memory images. Unit SysUtils Category comparison routines Delphi syntax: function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler ; C syntax: extern PACKAGE bool __fastcall CompareMem(void * P1, void * P2, int Length); Description CompareMem performs a binary compare of Length bytes of memory referenced by P1 to that of P2. CompareMem returns true if the memory referenced by P1 is identical to that of P2. ...Aquarius
------
水瓶男的blog: http://791909.blogspot.com
系統時間:2024-05-15 20:41:02
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!