【问题标题】:How to get the memory address of a file如何获取文件的内存地址
【发布时间】:2014-11-18 09:45:02
【问题描述】:

在 WCE 应用程序中,我正在寻找一种将文件(我只需要文件名/路径)复制到特定内存地址的方法。 该文件相当大,大约 40MB,因此在资源有限的情况下,我希望通过使用这篇文章的答案来避免将整个文件读入内存(字节数组): Copy data from from IntPtr to IntPtr

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] 
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); 
static void Main() 
{ 
    const int size = 200; 
    IntPtr memorySource = Marshal.AllocHGlobal(size); 
    IntPtr memoryTarget = Marshal.AllocHGlobal(size);
    CopyMemory(memoryTarget,memorySource,size); 
}

这给我留下了两个问题。 首先:如何为 IntPtr 分配内存地址?,有点像:int* startAddr = &0x00180000

其次:如何获取文件的内存地址?

回答完这两个问题后,我的代码将如下所示:

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
private unsafe void CopyFile()
{
    try
    {
        fixed (Int32* startAddr = /*0x00180000*/)
        {
            fixed(Int32* fileAddr = /*Memory Address of file*/)
            {
                CopyMemory(new IntPtr(startAddr), new IntPtr(fileAddr), (uint)new FileInfo("File name").Length);
            }
        }
    }
    catch { }
}

这是一种有效的方法吗?

任何帮助将不胜感激。提前致谢!!

更新: CopyMemory 不是解决问题的方法。所以请无视。

另外,很抱歉没有更清楚。基本上我想将文件移动到磁盘分区的开头。我认为 IntPtr 也可以指向磁盘地址,但回想起来我可以看到它当然不能。 无论如何,很抱歉造成混乱。

【问题讨论】:

  • 您可以简单地使用IntPtr 的ctor 为其分配地址:new IntPtr(0x00180000);,对于第二部分,文件在加载之前没有内存地址 -它在磁盘上,而不是在 RAM 中。
  • @aevitas 当然。非常感谢。不,你是对的。 CopyMemory 可能不是最好的方法。

标签: c# file memory-address


【解决方案1】:

文件在内存中没有地址。所以你要求的是不合逻辑的东西。

据我所知,您根本不需要任何不安全的代码。您无需致电CopyMemory。而且您不需要一次性加载整个文件然后复制。你可以做的如下:

  1. 使用标准文件流读取文件。
  2. 将文件以小块的形式读入一个小缓冲区。具体来说,您可以选择以 8KB 块的形式读取文件。
  3. 每次读取文件的一部分时,通过调用 Marshal.Copy 将其复制到非托管内存位置。

代码可能如下所示:

static void CopyStreamToMemory(Stream stream, IntPtr addr, int bufferSize)
{
    byte[] buffer = new byte[bufferSize];
    long bytesLeft = stream.Length - stream.Position;
    while (bytesLeft > 0)
    {
        int bytesToCopy = (int)Math.Min(bufferSize, bytesLeft);
        stream.Read(buffer, 0, bytesToCopy);
        Marshal.Copy(buffer, 0, addr, bytesToCopy);
        addr += bytesToCopy;
        bytesLeft -= bytesToCopy;
    }
}

【讨论】:

  • 这将是一个很好的简单方法。没有想到这一点。我会试一试,然后发布我想出的任何东西。非常感谢。
  • 顺便说一句,所以你的意思是 IntPtr 只能指向 RAM 内存?所以'new IntPtr(0x00180000)'不会给我一个指向地址0x00180000的磁盘的指针?
  • 没错。指针指的是内存。文件可以映射到内存中,但这是一项相当复杂的任务。我相信这不是你需要的。
  • 我当然会使用Stream 而不是低级指针的东西,除非你有一个基准表明这会导致不可接受的性能。低级解析代码中内存损坏的风险非常高,并且通常会导致严重的安全漏洞。
  • @David Heffernan。实际上,这正是我想要的。基本上我想将文件移动到磁盘分区的开头。很抱歉没有更清楚地说明这一点。我会更新 OP。
猜你喜欢
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 2012-07-05
  • 2015-01-08
  • 2021-01-05
相关资源
最近更新 更多