C# - 修改IntPtr指向的内容(替换字符串)

时间:2009-11-06 05:09:23

标签: c#

代码:

...

IntPtr buff

...

buff可以指向非常大的东西。这个buff将包含一个字符串,比方说“XYZ123”,我想用“ABC456”代替。不幸的是,其余数据不是字符串。这使我无法执行以下操作:

.. Marshal.PtrToStringAnsi(BUFF)

//在这里替换字符串

.. Marshal.StringToHGlobalAnsi(..)

因为它会搞砸其他“非字符串”二进制数据。鉴于大尺寸和我无法进行上述转换,最好的方法是做什么?

将Marshal.Copy放入循环中的byte []中,寻找字符序列吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

不确定我完全明白你要做什么。 但是,既然你不想搞乱非托管缓冲区,为什么不替换非托管缓冲区本身的字符串而不将其转换为托管字符串(并返回)?

只要字符串由'\ 0'(标准C字符串)分隔,您就可以查找要替换的字符串(例如“XYZ123”)。你可以自己做(通过char运行字符串char,使用指针算术)或者你甚至可以P / invoke

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);
}
编辑:我假设两个字符串长度相同。 (正如你的例子中所示)

答案 1 :(得分: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;
}