我想在c#中快速地从大小在500MB到1GB之间的二进制文件中删除不同位置的字节块,需要删除的字节的起始和长度在保存的数组中
int[] rdiDataOffset= {511,15423,21047};
int[] rdiDataSize={102400,7168,512};
编辑: 这是我的一段代码,除非我将缓冲区大小设置为1:
,否则它将无法正常工作while(true){
if (rdiDataOffset.Contains((int)fsr.Position))
{
int idxval = Array.IndexOf(rdiDataOffset, (int)fsr.Position, 0, rdiDataOffset.Length);
int oldRFSRPosition = (int)fsr.Position;
size = rdiDataSize[idxval];
fsr.Seek(size, SeekOrigin.Current);
}
int bufferSize = size == 0 ? 2048 : size;
if ((size>0) && (bufferSize > (size))) bufferSize = (size);
if (bufferSize > (fsr.Length - fsr.Position)) bufferSize = (int)(fsr.Length - fsr.Position);
byte[] buffer = new byte[bufferSize];
int nofbytes = fsr.Read(buffer, 0, buffer.Length);
fsr.Flush();
if (nofbytes < 1)
{
break;
}
}
答案 0 :(得分:4)
没有通用文件系统提供从现有文件中间删除块的有效方法(仅从末尾截断)。您必须在删除后将所有数据复制回适当的新位置。
答案 1 :(得分:1)
使用临时文件执行此操作的简单算法(也可以就地执行此操作,但如果出现问题则风险较高)。
创建一个新文件并调用SetLength来设置流大小(如果这太慢,则可以将Interop转换为SetFileValidData)。这可以确保您在复制时有空间存放临时文件。
按升序对删除列表进行排序。
从当前位置(从0开始)读取到第一个删除点。应该打开源文件而不授予写共享权限(在编辑时你不希望有人弄乱它)。
将该内容写入新文件(您可能需要以块的形式执行此操作)。
跳过未复制的数据
从#3开始重复直到
您现在有两个文件 - 旧文件和新文件...根据需要替换。如果这是非常关键的数据,您可能希望查看事务方法(您实现的方法或使用NTFS事务之类的方法)。
考虑新设计。如果您需要经常这样做,那么在文件中(或文件附近)包含一个包含非活动块列表的索引可能更有意义 - 然后在必要时您可以通过实际删除块来压缩文件。或者这就是这个过程。
答案 2 :(得分:0)
如果您使用的是NTFS文件系统(大多数Windows部署),并且您不介意进行p / invoke方法,那么有一种方法可以更快地从文件中删除块。您可以将文件设为稀疏。使用稀疏文件,您可以通过一次调用消除大量文件。
执行此操作时,不会重写该文件。相反,NTFS更新有关清零数据范围的元数据。稀疏文件的美妙之处在于,文件的使用者不必知道文件的稀疏性。也就是说,当您通过稀疏文件从FileStream读取时,将透明地跳过清零的扩展区。
NTFS使用此类文件进行自己的簿记。例如,USN期刊是一个非常大的稀疏内存映射文件。
制作文件稀疏和零文件部分的方法是使用DeviceIOControl windows API。它是神秘的并且需要p / invoke但是如果你走这条路线,你肯定会隐藏在漂亮的函数调用背后的uggles。
有一些问题需要注意。例如,如果将文件移动到非ntfs卷然后返回,则文件的稀疏性可能会消失 - 因此您应该进行防御性编程。
此外,稀疏文件看起来可能比实际大 - 使涉及磁盘配置的任务变得复杂。已完全清零的5g稀疏文件仍然会向用户的磁盘配额计算5g。
如果稀疏文件累积了很多漏洞,您可能需要偶尔在维护窗口中重写该文件。我还没有看到任何真正的性能问题,但我至少可以想象瑞士俗气的稀疏文件的元数据可能会导致性能下降。
如果你想了解这个想法,可以点击doc。[/ p>