2012-06-17 8 views
9

मेरे पास एक टेक्स्ट फ़ाइल है जो समय के साथ संलग्न है और समय-समय पर मैं इसे एक निश्चित आकार में छोटा करना चाहता हूं, उदा। 10 एमबी, लेकिन पहले की तुलना में अंतिम 10 एमबी रखते हुए।फ़ाइल को कुछ आकार में कैसे छोटा करें लेकिन अंत अनुभाग रखें?

क्या ऐसा करने के लिए कोई चालाक तरीका है? मुझे लगता है कि मुझे सही बिंदु की तलाश करनी चाहिए, वहां से एक नई फाइल में पढ़ना चाहिए, पुरानी फ़ाइल हटाएं और पुरानी नाम पर नई फाइल का नाम बदलें। कोई बेहतर विचार या उदाहरण कोड? आदर्श रूप से मैं पूरी फ़ाइल को स्मृति में नहीं पढ़ूंगा क्योंकि फ़ाइल बड़ी हो सकती है।

कृपया log4net आदि का उपयोग कर

उत्तर

4

तुम सिर्फ स्मृति में पिछले 10 एमबी पढ़ने के साथ ठीक हैं, तो यह काम करना चाहिए:

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 भी आवश्यकता हो सकती है के एक कार्यान्वयन हो सकता है एक ms.Position = 0 से पहले अंतिम CopyTo() (मैं इस्तेमाल किया एक और फ़ाइलस्ट्रीम मेमोरीस्ट्रीम नहीं) – StuartLC

+0

@nonnb: अच्छा बिंदु; धन्यवाद। – Ryan

+0

@minitech ऐसा लगता है कि आपका कोड केवल .NET 4.0 अप से काम कर रहा है। मैंने पाया कि मेरे .NET 3.5 प्रोजेक्ट पर कोडिंग करते समय। – Alex

4

विशेष रूप से नहीं करता है, तो आप एक अलग फ़ाइल में लिख रहे हैं आप, यह लिखने से पहले पूरी फ़ाइल को पढ़ने की जरूरत नहीं है पर कोई सुझाव नहीं। आप भाग में काम कर सकते हैं; थोड़ा सा पढ़ना, लिखना, थोड़ा और पढ़ना, फिर से लिखना। वास्तव में, इस तरह सभी I/O वैसे भी किया जाता है। विशेष रूप से बड़ी फ़ाइलों के साथ आप वास्तव में कभी भी उन्हें एक साथ पढ़ना नहीं चाहते हैं।

लेकिन जो भी आप प्रस्तावित करते हैं वह फ़ाइल की शुरुआत से डेटा को हटाने का एकमात्र तरीका है। आपको इसे फिर से लिखना होगा। Raymond Chen has a blog post on exactly that topic, too.

1

आप फ़ाइल को बाइनरी स्ट्रीम में पढ़ सकते हैं और अंतिम 10 एमबी डेटा को पुनः प्राप्त करने के लिए खोज विधि का उपयोग कर सकते हैं और उन्हें स्मृति में लोड कर सकते हैं। फिर आप इस स्ट्रीम को एक नई फाइल में सहेजते हैं और पुराने को हटा देते हैं। टेक्स्ट डेटा को छोटा कर दिया जा सकता है, हालांकि आपको यह तय करना होगा कि यह छोड़कर है या नहीं।

शोध विधि का एक उदाहरण के लिए यहाँ देखो:

http://www.dotnetperls.com/seek

+0

हाँ कोड minitech द्वारा प्रदान उदाहरण मेरी porposition :) –

2

मैं परीक्षण किया "झूठी" से समाधान लेकिन यह मेरे लिए काम नहीं करता है, यह फ़ाइल को ट्रिम करता है लेकिन इसकी शुरुआत करता है, अंत में नहीं।

मुझे संदेह है कि 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); 
    } 
} 
+0

मैं अपने पर्यावरण में इसकी पुष्टि करता हूं (WMC 64 बिट्स के साथ Win8.1 प्रो, .NET 4.6.1, C#)। मेरे विशेष मामले में, 'सुश्री कॉपी' सही नहीं है। इसे 'fs.Write (ms.GetBuffer(), 0, trimSize) के साथ बदल दिया; '(मैं इसका उपयोग कर रहा हूं (http://stackoverflow.com/a/11072529/1273042) समाधान)। समस्या को इंगित करने के लिए +1 (: – mishamosher

संबंधित मुद्दे