2014-03-04 43 views
0

我需要將文件的前100個字節移動到文件末尾,然後保存該文件(Windows窗體應用程序)。然後我需要相反的過程(將最後的100個字節移回開頭,然後再保存)。將文件的前100個字節移動到文件的末尾,然後再保存並再次保存

其中一些文件非常大(超過2GB),所以我不能使用file.readallbytes,因爲我內存不足異常。

我試着玩文件流和使用filestream.position,但我無法包住我的頭移動字節,然後保存該文件。

任何指導將不勝感激。

+1

這將涉及物理移動字節。所以你只要讀取第101個字節並寫入第1個字節即可。然後,第102個到第2個,...然後您將最初存儲在某個數組中的前100個字節追加到最後並獲得一個贏家啤酒。 – zerkms

+0

我很好,只是使第一個100字節0的,如果這使得它更容易,然後將它們添加到文件的末尾。然後當發生相反的情況時,用結尾的實際值替換那些0字節並刪除尾部的100 ... –

回答

3

的關鍵是使用一個字節緩衝器,所以你僅在一次處理的文件的一小部分。這聽起來像你有正確的方法,但一路上有一些陷阱。

下面是示出如何我接近它的一個示例:

public enum SwapType 
{ 
    FrontToBack, 
    BackToFront 
} 

public static class EndSwap 
{ 
    public static void DoSwap(string path, SwapType swapType) 
    { 
     if (path == null) 
     { 
      throw new ArgumentNullException("path", 
       "You must supply a path to the file."); 
     } 
     if (!File.Exists(path)) 
     { 
      throw new FileNotFoundException("File not found."); 
     } 

     string tempPath = Path.GetTempFileName(); 
     byte[] buffer = new byte[4096]; 
     byte[] swapBytes = new byte[100]; 

     using (FileStream inputFs = new FileStream(path, FileMode.Open, 
      FileAccess.Read)) 
     using (FileStream outputFs = new FileStream(tempPath, 
      FileMode.Open, FileAccess.Write)) 
     { 
      int bytesRead = -1; 

      if (swapType == SwapType.FrontToBack) 
      { 
       // We want to keep hold of the first 100 bytes of the file 
       // and output them after copying the rest of file 
       inputFs.Read(swapBytes, 0, 100); 
      } 
      else 
      { 
       // Read the last 100 bytes of the file 
       inputFs.Seek(-100, SeekOrigin.End); 
       inputFs.Read(swapBytes, 0, 100); 
       // Output them straight to the output file 
       outputFs.Write(swapBytes, 0, 100); 
       // Reposition to the beginning of the input file 
       inputFs.Seek(0, SeekOrigin.Begin); 
      } 

      // The number of bytes left to copy is 100 less than the file 
      // length 
      long bytesRemaining = inputFs.Length - 100; 

      // Copy the rest of the bytes 
      while (bytesRemaining > 0) 
      { 
       bytesRead = inputFs.Read(buffer, 0, buffer.Length); 
       // NB: the number of bytes read could be more than the 
       // number remaining 
       outputFs.Write(buffer, 0, 
        (int)Math.Min(bytesRead, bytesRemaining)); 
       bytesRemaining -= bytesRead; 
      } 

      // Don't forget to append the start bytes if required 
      if (swapType == SwapType.FrontToBack) 
      { 
       outputFs.Write(swapBytes, 0, 100); 
      } 
     } 

     // Now swap the files themselves 
     File.Delete(path); 
     File.Move(tempPath, path); 
     // NB: could do File.Replace() if backup is needed 
    } 
} 

實例:

// Copy first 100 bytes to end 
EndSwap.DoSwap(@"C:\Users\Dave\Downloads\MyTest.pdf", SwapType.FrontToBack); 
// Copy those same 100 bytes back to the beginning again 
EndSwap.DoSwap(@"C:\Users\Dave\Downloads\MyTest.pdf", SwapType.BackToFront); 

最終的結果是相同的原始文件,當然。

+0

這是完美的。我希望我可以將這兩個答案都標記爲正確的,但是由於您提供瞭如何將其恢復的完整方式,所以這個更好是因爲我試圖找出另一個答案的返回路徑。謝謝。仍然爲你們+1 +1) –

4

您不應將所有數據讀入內存。通過使用FileStream,您可以讀取多個數據塊,例如每個1 KB,並將其存儲在新文件中。從位置100開始,跳過第一個字節。重新整理完整文件後,在末尾添加跳過的字節。最後將新文件移動到舊文件的位置。通過提高maxBufferSize,您可以固定複製過程,但使用更多的內存。

要恢復更改,請從最後100個字節開始,然後從開始直到inputStream.Length - 100

string inputFile = "C:\\input.txt"; 
string tempFile = "C:\\input.txt"; 
int dataLength = 100; 
int maxBufferSize = 1024; 

using (var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read)) { 
    int length = (int)inputStream.Length; 
    int currentInputPosition = dataLength; 

    inputStream.Position = currentInputPosition; 

    using (var outputStream = new FileStream(tempFile, FileMode.Create, FileAccess.ReadWrite)) { 
     var bufferSize = Math.Min(maxBufferSize, length - currentInputPosition); 

     var buffer = new byte[bufferSize]; 
     while (inputStream.Read(buffer, 0, bufferSize) > 0) { 
      currentInputPosition += bufferSize; 

      outputStream.Write(buffer, 0, buffer.Length); 
     } 

     buffer = new byte[dataLength]; 
     inputStream.Position = 0; 
     inputStream.Read(buffer, 0, buffer.Length); 
     outputStream.Write(buffer, 0, buffer.Length); 
    } 
} 

File.Delete(inputFile); 
File.Move(tempFile, inputFile); 
+0

非常感謝。儘管我對轉換有點困惑。我從最後100開始,如下所示:int currentInputPosition = length - 100;並在我的while循環中將這些前100個字節寫入新文件。我然後設置我的currentInputPosition = 0;從一開始就開始,但我不確定在哪裏放置循環的邊界來停止? –

相關問題