2012-06-17 17 views
9

Zaman içinde eklenmiş ve belirli bir boyuta kısaltmak istiyorum periyodik olarak eklenmiş bir metin dosyası var, ör. 10MB, ancak ilk 10MB yerine ilk 10MB tutmak.Bir dosyayı belirli bir boyuta kırpmak ancak bitiş bölümünü tutmak nasıl?

Bunu yapmanın akıllıca bir yolu var mı? Sanırım doğru noktaya gitmeli, oradan yeni bir dosyaya bakmalı, eski dosyayı silmeli ve yeni dosyayı eski isimle değiştirmeliyim. Daha iyi bir fikir veya örnek kod? İdeal olarak dosyanın tamamını büyük tutabildiğinden tüm dosyayı hafızada okumamıştım. Eğer farklı bir dosyaya yazıyoruz özellikle de eğer bunu yazmadan önce tüm dosyayı okumak gerekmez vb Log4Net

cevap

4

, bu çalışması gerekir:

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); 
    } 
} 
+4

1 de ihtiyacım olabilir bir uygulama olabilir ms.Position = 0 nihai CopyTo() (kullandım önce Başka bir FileStream değil MemoryStream) – StuartLC

+0

@nonnb: İyi nokta; Teşekkürler. – Ryan

+0

@minitech Kodunuzun SADECE .NET 4.0 sürümünden çalışıyormuş gibi görünüyor. .NET 3.5 projemi kodlarken bunu keşfettim. – Alex

4

kullanımıyla ilgili

Lütfen hiçbir öneri. Parçalarda çalışabilirsiniz; biraz okuma, yazma, biraz daha okuma, tekrar yazma. Aslında, tüm G/Ç işlemleri böyle yapılır. Özellikle büyük dosyalarda, hepsini bir kerede okumak istemezsiniz.

Ama sizin önerdiğiniz şey, verileri bir dosyanın başlangıcından kaldırmanın tek yoludur. Yeniden yazmalısın. Raymond Chen has a blog post on exactly that topic, too.

1

Dosyayı bir ikili akışa okuyabilir ve son 10MB'lık verileri almak ve bunları belleğe yüklemek için arama yöntemini kullanabilirsiniz. Sonra bu akışı yeni bir dosyaya kaydedip eski dosyayı silersiniz. Metin verileri kesilebilir, bu yüzden bu durumun kabul edilebilir olup olmadığına karar vermelisiniz. Seek yöntemini bir örnek için burayı

Bak: sadece belleğe son 10MB'yi okuma yapmayı kabul ediyorsanız

http://www.dotnetperls.com/seek

+0

Evet minitech tarafından sağlanan kod örneği benim porposition :) –

2

ben test “yanlış” dan çözüm ama benim için işe yaramazsa, dosyayı düzeltir, ancak başlangıcını değil, sonunu tutar.

CopyTo yayın akışına başlamak yerine tüm akışı kopyalar sanıyorum. İşte o iş yapılmış edebilirsiniz:

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); 
    } 
} 
+0

Bunu çevremde (Win8.1 Pro ile WMC 64 bit, .NET 4.6.1, C#) onaylıyorum. Benim özel durumumda, ms.CopyTo (s) 'doğru çalışmıyor. 'Fs.Write (ms.GetBuffer(), 0, trimSize) ile değiştirildi;' ([this] kullanıyorum (http://stackoverflow.com/a/11072529/1273042)). Sorunu belirtmek için +1 (: – mishamosher

İlgili konular