2009-11-06 64 views
0

代碼:C# - 修改什麼的IntPtr指向(替換字符串)

...

IntPtr的BUFF

...

愛好者可以指向的東西相當大。這個buff將包含一個字符串,可以說「XYZ123」,我想用「ABC456」替換。不幸的是,其餘的數據不是字符串。這是阻止我做類似如下:

..Marshal.PtrToStringAnsi(BUFF)

//做字符串替換這裏

..Marshal.StringToHGlobalAnsi(..)

因爲它會搞砸其他「非字符串」的二進制數據。鑑於尺寸較大,以及我無法進行上述轉換,要做到這一點,最好的方法是什麼?

在一個循環中執行一個Marshal.Copy到一個byte []中,尋找一個字符序列?

謝謝!

回答

0

不確定我完全明白你想要做什麼。 但是,由於您不想混淆非託管緩衝區,爲什麼不替換非託管緩衝區中的字符串而不將其轉換爲託管字符串(並返回)呢?

只要字符串由'\ 0'(標準C字符串)分隔,您就可以查找要替換的字符串(例如「XYZ123」)。你可以自己做(走成炭串字符,用指針運算),或者你甚至可以P /調用

LPTSTR StrStr(   
LPCTSTR lpFirst, 
    LPCTSTR lpSrch 
); 

從SHLWAPI.DLL

一旦你找到了指向字符串(「XYZ123 「)你可以用類似的東西代替它:

LPTSTR StrCpy(
    LPTSTR psz1, 
    LPCTSTR psz2 
); 

或者再次,自己實現它。

注:上述功能有安全的選擇。請參閱:Security Considerations: Microsoft Windows Shell

以下示例顯示如何使用不安全的代碼和IntPtr。它可能有所幫助:

public unsafe static void Main() 
{ 
    int a = 10; 
    Console.WriteLine("a is {0} ({0:X})", a); 
    IntPtr ip = new IntPtr(&a); 
    byte* pTarget = (byte*)ip.ToPointer() + 1; 
    *pTarget = 2; 

    Console.WriteLine("a is {0} ({0:X})", a); 
} 

編輯:我假設兩個字符串是相同的長度。 (因爲他們在你的例子)

0

鑑於你的字節數組很大,我不會一直複製它。
從我的角度來看,你要麼需要

  • 寫一個C函數,並調用它的C#代碼
  • 寫一個比較和交換功能不安全C#類似於從dtroy示例代碼。

這是一些未經測試的代碼,您可以嘗試:

static unsafe Boolean Compare(byte* src, byte * compare, int size) 
{ 
    Boolean result = true; 
    int i = 0; 
    while (result && i < size) 
    { 
     result=result&&*(src+i)==*(compare+i); 
    } 
    return result; 
} 

static unsafe void Replace (byte* src, byte* newData, int size) { 
    for (int i = 0; i < size; i++) 
     *(src + i) = *(newData + i); 
} 

static unsafe Boolean Swap(IntPtr ptr, byte[] search, byte[] newData, int ptrBytes) 
{ 
    Boolean result = false; 
    byte* pSearch = (byte*) Marshal.UnsafeAddrOfPinnedArrayElement(search, 0); 
    byte* pReplace = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(newData, 0); 
    for (int i = 0; i < ptrBytes - search.Length;i++) 
    { 
     byte* pTarget = (byte*)ptr.ToPointer()+i; 
     if (Compare(pTarget, pSearch, search.Length)) 
     { 
      Replace(pTarget, pReplace, newData.Length); 
      return true; 
     } 
    } 
    return result; 
}