读书人

内存映射用法不同导致结果差异悬殊

发布时间: 2012-05-31 12:19:24 作者: rapoo

内存映射,用法不同导致结果差异悬殊,百思不得其解。
新近写的代码用到内存映射,遇到了一个百思不得其解的问题:
使用“代码1”时,Program 类中 for 循环输出结果(最初1K字节)正确;

使用“代码1”时,Program 类中 for 循环输出结果(最初1K字节)错误,
但是:代码2中 if(i==0) 时,结果正确;
   而改 if(i==1) 时,结果同 Program 类中 for 循环,错误

郁闷至极,不知道错在哪?请大虾指教。

代码摘抄如下:

C# code
public class FileMap{    public List<byte[]> list = null;    public void Test(string path)    {        list = new List<byte[]>();        ...        long fileOffset = 0;        long fileSize = 0;        uint blockBytes = 64<<20;//64M        while (fileSize > 0)        {            IntPtr lpbMapAddress = MapViewOfFile(mappingFileHandle, FILE_MAP_COPY | FILE_MAP_READ,(uint)(fileOffset >> 32), (uint)(fileOffset & 0xFFFFFFFF),blockBytes);            byte[] temp = new byte[blockBytes];            // 代码1,Program 类中 for 循环输出结果(最初1K字节)正确            Marshal.Copy(lpbMapAddress, temp, 0, (int)blockBytes);            list.Add(temp);            // end:代码1            // 代码2,Program 类中 for 循环输出结果(最初1K字节)错误,但是代码2中 if(i==0) 时,结果正确;而改 if(i==1) 时,结果同 Program 类中 for 循环,错误            byte[] tmp = new byte[1024];            for(int i = 0; i < temp.Length; i+=1024)            {                Array.Clear(tmp,0,tmp.Length);                Buffer.BlockCopy(temp, i, tmp, 0, 1024);                //输出最初1K字节                if(i==0)// i==0:正确;i==1:错误                {                    for(int j = 0; j < 1024; j++)                    {                        Console.Write(tmp[j].ToString("X2")+",");                    }                }                list.Add(tmp);            }            // end:代码2            UnmapViewOfFile(lpbMapAddress);            fileOffset += blockBytes;            fileSize -= blockBytes;        }    }}public class Program{    static void Main(string[] args)    {        FileMap fileMap = new FileMap();        fileMap.Test(@"test.rar");//文件大小:8388608B = 8M        Console.WriteLine(fileMap.list.Count.ToString());// 结果正确,代码1结果为:1,代码2结果为:8192        byte[] temp = (byte[])(fileMap.list[0]);        for(int i = 0; i < 1024; i++)        {            Console.Write(temp[i].ToString("X2")+",");        }    }}


[解决办法]
用代码1,结合以下用法,应该达到你想要的效果,当然,如果输出的文件与原文件相同的话。
C# code
for(int i=0;i<fileMap.list.Count;i++){    for(int j=0;j<fileMap.list[i].Length;j+=1024)    {        stream.Seek(j,SeekOrigin.Begin);        stream.Write(fileMap.list[i], j, 1024);    }}
[解决办法]
tmp变量是引用类型,因此你list.Add(tmp);只是添加了它的引用地址而并非里面的字节内容,当i>0时,即添加了第二次以上时,每次添加的都是相同的tmp引用,结果第二次你刷新tmp内容就把第一次的内容给改掉了。

读书人网 >C#

热点推荐