2013-08-05 37 views
1

对于某些项目,我需要覆盖文件,但是因为用户可能还会用其他程序编辑此文件,同时我不会在运行时经常保留流,但会将所有数据保存在字节数组。当保存我的程序时,应该只保存它编辑的区域,而不是整个文件。我已经(很不好)写了一个例程来这样做,但它预计很慢,我不知道如何提高性能。实际上,我只是通过整个数组循环,没有那么聪明,因为它似乎:优化“修补程序”过程

public Boolean Patch(string path) 
    { 
     FileStream fs = new FileStream(path, FileMode.Open); 
     BinaryReader br = new BinaryReader(fs); 
     BinaryWriter bw = new BinaryWriter(fs); 
     if (fs.Length != this.rawdata.Length) 
      throw new ArgumentException(); 
     for (int i = 0; i < this.rawdata.Length; ++i) 
     { 
      if (br.ReadByte() != rawdata[i]) 
      { 
       fs.Position--; 
       bw.Write(rawdata[i]); 
      } 
     } 
     fs.Close(); 
     return true; 
    } 
+0

这似乎是一个灾难。你不想保存整个文件,因为用户可能正在编辑另一个程序?你处理的唯一情况是如果文件大小不同。如果用户改变了您正在更改的确切代码块中的内容,该怎么办?答:你会覆盖他们的变化。从本质上来说,您的应用程序将保留用户所做的临时更改。如果用户从文件的开头删除3个字节,但在结尾添加3个字节会怎样?然后一切都不同步。 – NotMe

+0

最好的办法是锁定该文件,不要让用户在应用程序关闭之前在应用程序之外进行编辑。 – NotMe

回答

0

您对硬盘驱动器(或任何其他流)的每一个访问,是昂贵的。 将您的代码转换为使用下一个要读取的X(例如1024)字节和要写入的Y(例如1024)字节的高速缓存副本。

我没有完全理解你的代码是应该做的,但说你要复制流之间的文件,你的函数应该是在精神:

private const int BUFFER_SIZE = 1024; 

void copy(BinaryReader inStream, BinaryWriter outStream) 
{ 
    byte[] cache = new byte[BUFFER_SIZE]; 
    int readCount = 0; 
    while ((readCount = inStream.Read(cache, 0, BUFFER_SIZE)) != 0) 
    { 
     outStream.Write(cache, 0, readCount); 
    } 
} 

在这个例子中,BUFFER_SIZE不要太小(所以批量阅读和写作会很有效),而不是太大 - 满溢你的记忆。
在您的代码示例中,您每次读取一个字节(即BUFFER_SIZE = 1),因此会降低应用程序的速度。

编辑:添加你需要写代码:

public Boolean Patch(string path) 
    { 
     const int BUFFER_SIZE = 512; 

     // VERY IMPORTANT: The throw operation will cause the stream to remain open the function returns. 
     using (FileStream fs = new FileStream(path, FileMode.Open)) 
     { 
      BinaryReader br = new BinaryReader(fs); 
      BinaryWriter bw = new BinaryWriter(fs); 
      if (fs.Length != this.rawdata.Length) 
       throw new ArgumentException(); 
      byte[] cache = new byte[BUFFER_SIZE]; 
      int readCount = 0, location = 0; 
      while ((readCount = br.Read(cache, 0, BUFFER_SIZE)) != 0) 
      { 
       int changeLength = 0; 

       for (int j = 0; j < readCount; j++) 
       { 
        if (cache[j] != rawdata[j + location]) 
        { 
         changeLength++; 
        } 
        else if (changeLength > 0) 
        { 
         fs.Position = location + j - changeLength; 
         bw.Write(rawdata, location + j - changeLength, changeLength); 
         fs.Position = location + j; 

         changeLength = 0; 
        } 
       } 

       location += readCount; 
      } 

      return true; 
     } 
    } 
+0

我只需要写东西到特定的地方,“修补”文件就可以这么说。我想你的建议正是BinaryWriter.Write(byte [])所做的。 – user2642796

+0

如果你在一个缓存的字节数组上工作,然后把它作为一个整体写到所需的位置,会更好。 – EZSlaver

+0

了解这一点: 硬盘驱动器是块设备,意味着您一次访问其内容块。内存(随机存取内存或RAM)单元直接访问。当你有一个正常的数组时,它位于计算机的内存中,因此遍历每个元素是基本的和快速的。另一方面,当你在硬盘上有一个阵列时,每次加载其中的一部分(像存储器可以处理的那么大)并且迭代它们会更有效率。从硬盘加载某些内容时,访问数据的速度不如内存访问快。 – EZSlaver