我有一個隨時間附加的文本文件,並且週期性地將其截斷爲一定的大小,例如, 10MB,但保留最後的10MB而不是第一個。如何將文件截斷爲特定大小但保留最終部分?
有沒有什麼聰明的方法可以做到這一點?我猜我應該尋求正確的觀點,從那裏讀入一個新文件,刪除舊文件並將新文件重命名爲舊名稱。任何更好的想法或示例代碼?理想情況下,我不會將整個文件讀入內存,因爲該文件可能很大。
請使用log4net的等
我有一個隨時間附加的文本文件,並且週期性地將其截斷爲一定的大小,例如, 10MB,但保留最後的10MB而不是第一個。如何將文件截斷爲特定大小但保留最終部分?
有沒有什麼聰明的方法可以做到這一點?我猜我應該尋求正確的觀點,從那裏讀入一個新文件,刪除舊文件並將新文件重命名爲舊名稱。任何更好的想法或示例代碼?理想情況下,我不會將整個文件讀入內存,因爲該文件可能很大。
請使用log4net的等
如果沒有問題,只需讀最後10MB內存,這應該工作:
using(MemoryStream ms = new MemoryStream(10 * 1024 * 1024)) {
using(FileStream s = new FileStream("yourFile.txt", FileMode.Open, FileAccess.ReadWrite)) {
s.Seek(-10 * 1024 * 1024, SeekOrigin.End);
s.CopyTo(ms);
s.SetLength(10 * 1024 * 1024);
s.Position = 0;
ms.Position = 0; // Begin from the start of the memory stream
ms.CopyTo(s);
}
}
你不需要寫之前讀取整個文件,特別是沒有如果你正在寫到不同的文件中沒有任何建議。你可以分塊工作;讀一點,寫作,再讀一點,再寫一遍。事實上,這就是所有I/O都是如何完成的。特別是對於較大的文件,您永遠不會真正想要一次讀取它們。
但是,您提出的是從文件開頭刪除數據的唯一方法。你必須重寫它。 Raymond Chen has a blog post on exactly that topic, too.
您可以將文件讀取到二進制流中,並使用seek方法來檢索最後10MB的數據並將它們加載到內存中。然後將此流保存到一個新文件中,並刪除舊文件。文本數據可能會被截斷,因此您必須確定這是否可以解決。
在這裏尋找Seek方法的一個例子:
是由MiniTech移動提供的代碼示例可能是我porposition :) –
我測試從「假」的解決方案,但它不適用於我,它修剪文件,但保持它的開始,而不是結束。
我懷疑CopyTo
複製整個流而不是開始流位置。以下是我做它的工作:
int trimSize = 10 * 1024 * 1024;
using (MemoryStream ms = new MemoryStream(trimSize))
{
using (FileStream s = new FileStream(logFilename, FileMode.Open, FileAccess.ReadWrite))
{
s.Seek(-trimSize, SeekOrigin.End);
byte[] bytes = new byte[trimSize];
s.Read(bytes, 0, trimSize);
ms.Write(bytes, 0, trimSize);
ms.Position = 0;
s.SetLength(trimSize);
s.Position = 0;
ms.CopyTo(s);
}
}
我在我的環境中確認了這一點(Win8.1 Pro,WMC 64位,.NET 4.6.1,C#)。在我的特殊情況下,'ms.CopyTo(s)'不起作用。使用'fs.Write(ms.GetBuffer(),0,trimSize);'(我正在使用[this](http://stackoverflow.com/a/11072529/1273042)解決方案)更改它。 +1指出問題(: – mishamosher
+1可能還需要一實現方式ms.Position = 0最終CopyTo從()(我使用之前另一個FileStream不是MemoryStream) – StuartLC
@nonnb:好點;謝謝。 – Ryan
@minitech看來你的代碼只能從.NET 4.0開始工作。我發現,雖然編碼在我的.NET 3.5項目。 – Alex