2009-12-28 12 views
18

में एक पाठ फ़ाइल की एक विशेष लाइन मैं दो पाठ फ़ाइलें, Source.txt और Target.txt है। स्रोत को कभी भी संशोधित नहीं किया जाएगा और इसमें टेक्स्ट की एन पंक्तियां शामिल होंगी। इसलिए, मैं Target.txt में टेक्स्ट की एक विशिष्ट पंक्ति को हटाना चाहता हूं, और Source.txt से टेक्स्ट की एक विशिष्ट पंक्ति से प्रतिस्थापित करना चाहता हूं, मुझे पता है कि मुझे कितनी लाइन चाहिए, वास्तव में लाइन नंबर 2, दोनों फाइलें हैं। इस तरहसंपादित करें सी #

मैं हेवन कुछ:

string line = string.Empty; 
int line_number = 1; 
int line_to_edit = 2; 

using (StreamReader reader = new StreamReader(@"C:\source.xml")) 
{ 
    using (StreamWriter writer = new StreamWriter(@"C:\target.xml")) 
    { 
     while ((line = reader.ReadLine()) != null) 
     { 
      if (line_number == line_to_edit) 
      { 
       writer.WriteLine(line); 
      } 

      line_number++; 
     } 
    } 
} 

लेकिन जब मैं लेखक खोलते हैं, तो लक्ष्य फ़ाइल मिट जाते हैं, यह लाइनें लिखते हैं, लेकिन, जब खोला, लक्ष्य फ़ाइल केवल की नकल की रेखाएं हों, बाकी खो जाओ।

मैं क्या कर सकता हूं?

उत्तर

38

आप पूरी फ़ाइल को फिर से लिखने (जब तक कि लाइनों की लम्बाई समान होने के लिए होता है) के बिना एक लाइन को फिर से लिखने नहीं कर सकते। यदि आपकी फ़ाइलें छोटी हैं तो संपूर्ण लक्ष्य फ़ाइल को स्मृति में पढ़ना और फिर इसे फिर से लिखना समझ में आता है। आप क्या कर सकते हैं कि इस तरह:

using System; 
using System.IO; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     int line_to_edit = 2; // Warning: 1-based indexing! 
     string sourceFile = "source.txt"; 
     string destinationFile = "target.txt"; 

     // Read the appropriate line from the file. 
     string lineToWrite = null; 
     using (StreamReader reader = new StreamReader(sourceFile)) 
     { 
      for (int i = 1; i <= line_to_edit; ++i) 
       lineToWrite = reader.ReadLine(); 
     } 

     if (lineToWrite == null) 
      throw new InvalidDataException("Line does not exist in " + sourceFile); 

     // Read the old file. 
     string[] lines = File.ReadAllLines(destinationFile); 

     // Write the new file over the old file. 
     using (StreamWriter writer = new StreamWriter(destinationFile)) 
     { 
      for (int currentLine = 1; currentLine <= lines.Length; ++currentLine) 
      { 
       if (currentLine == line_to_edit) 
       { 
        writer.WriteLine(lineToWrite); 
       } 
       else 
       { 
        writer.WriteLine(lines[currentLine - 1]); 
       } 
      } 
     } 
    } 
} 

अपनी फ़ाइलें बड़ी है ताकि वह आपको एक फ़ाइल से स्ट्रीमिंग जब आप अन्य को लिखने पढ़ सकते हैं एक नई फ़ाइल बनाने के लिए बेहतर होगा रहे हैं। इसका मतलब है कि आपको पूरी फाइल को स्मृति में एक बार में रखने की आवश्यकता नहीं है। आप क्या कर सकते हैं कि इस तरह:

using System; 
using System.IO; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     int line_to_edit = 2; 
     string sourceFile = "source.txt"; 
     string destinationFile = "target.txt"; 
     string tempFile = "target2.txt"; 

     // Read the appropriate line from the file. 
     string lineToWrite = null; 
     using (StreamReader reader = new StreamReader(sourceFile)) 
     { 
      for (int i = 1; i <= line_to_edit; ++i) 
       lineToWrite = reader.ReadLine(); 
     } 

     if (lineToWrite == null) 
      throw new InvalidDataException("Line does not exist in " + sourceFile); 

     // Read from the target file and write to a new file. 
     int line_number = 1; 
     string line = null; 
     using (StreamReader reader = new StreamReader(destinationFile)) 
     using (StreamWriter writer = new StreamWriter(tempFile)) 
     { 
      while ((line = reader.ReadLine()) != null) 
      { 
       if (line_number == line_to_edit) 
       { 
        writer.WriteLine(lineToWrite); 
       } 
       else 
       { 
        writer.WriteLine(line); 
       } 
       line_number++; 
      } 
     } 

     // TODO: Delete the old file and replace it with the new file here. 
    } 
} 

आप बाद में फ़ाइल ले एक बार आप यह सुनिश्चित करें कि लिखने आपरेशन सफल रहा है कर रहे हैं (कोई excecption फेंक दिया गया था और लेखक बंद कर दिया है) कर सकते हैं।

नोट दोनों ही मामलों में यह थोड़ा भ्रामक है कि है कि आप अपने लाइन नंबर के लिए 1 आधारित अनुक्रमण का उपयोग कर रहे हैं। 0-आधारित अनुक्रमण का उपयोग करने के लिए यह आपके कोड में अधिक समझ सकता है। यदि आप चाहें तो आपके प्रोग्राम में आपके यूजर इंटरफेस में 1-आधारित इंडेक्स हो सकता है, लेकिन इसे आगे भेजने से पहले इसे 0-इंडेक्स में परिवर्तित कर सकता है।

इसके अलावा, सीधे नई फ़ाइल के साथ पुरानी फाइल को अधिलेखित करने का एक नुकसान यह है कि अगर यह के माध्यम से आधे रास्ते में विफल रहता है तो आप स्थायी रूप से खो सकता है जो कुछ भी डेटा नहीं लिखा गया था है। किसी तीसरे फ़ाइल पर लिखकर पहले आप यह सुनिश्चित करने के बाद केवल मूल डेटा हटा देते हैं कि आपके पास एक और (सही) प्रतिलिपि है, इसलिए यदि डेटा आधे रास्ते से दुर्घटनाग्रस्त हो जाता है तो आप डेटा पुनर्प्राप्त कर सकते हैं।

एक अंतिम टिप्पणी: मैंने देखा है कि आपकी फ़ाइलों को एक xml विस्तार किया था। आप इस बात पर विचार करना चाहेंगे कि विशिष्ट लाइनों को बदलने की बजाय फ़ाइलों की सामग्री को संशोधित करने के लिए आपके लिए XML पार्सर का उपयोग करना अधिक समझ में आता है या नहीं।

2

जब आप StreamWriter बनाते हैं तो यह हमेशा स्क्रैच से एक फ़ाइल बनाते हैं, आपको एक तीसरी फ़ाइल बनाना होगा और लक्ष्य से प्रतिलिपि बनाना होगा और आपको जो चाहिए उसे प्रतिस्थापित करें, और फिर पुराने को प्रतिस्थापित करें। लेकिन जैसा कि मैं देख सकता हूं कि आपको एक्सएमएल मैनिपुलेशन की आवश्यकता है, तो आप XmlDocument का उपयोग करना चाहेंगे और एक्सपैथ का उपयोग करके अपनी फ़ाइल को संशोधित कर सकते हैं।

1

मुझे लगता है कि नीचे (अपने उदाहरण से लेखक भाग के बजाय) काम करना चाहिए। मेरे पास कोई निर्माण पर्यावरण के साथ दुर्भाग्य से कर रहा हूँ तो यह स्मृति से है, लेकिन मुझे आशा है कि यह मदद करता है

using (var fs = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite))) 
     { 
      var destinationReader = StreamReader(fs); 
      var writer = StreamWriter(fs); 
      while ((line = reader.ReadLine()) != null) 
      { 
       if (line_number == line_to_edit) 
       { 
        writer.WriteLine(lineToWrite); 
       } 
       else 
       { 
        destinationReader .ReadLine(); 
       } 
       line_number++; 
      } 
     } 
2

आप बजाय एक नया StreamReader है, जो हमेशा आउटपुट फ़ाइल अधिलेखित कर देता है का उपयोग करने से लेखन पहुँच के लिए उत्पादन फ़ाइल को खोलने की जरूरत है।

StreamWriter stm = null; 
fi = new FileInfo(@"C:\target.xml"); 
if (fi.Exists) 
    stm = fi.OpenWrite(); 
बेशक

, आप अभी भी, आउटपुट फ़ाइल में सही लाइन है, जो मुश्किल हो जाएगा क्योंकि आप इसे से नहीं पढ़ सकते हैं करने के लिए तलाश करने के लिए तो जब तक आप पहले से ही पता बाइट के लिए तलाश करने के लिए ऑफसेट होगा, आप शायद वास्तव में पढ़ना/लिखना चाहते हैं।

FileStream stm = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); 
इस धारा के साथ

, आप जब तक आप, बिंदु जहाँ आप परिवर्तन करना चाहते हैं के लिए मिलता है तो लिख पढ़ सकते हैं। ध्यान रखें कि आप लाइनों को ओवरराइट करने के लिए बाइट्स लिख रहे हैं, इसलिए लाइन को उसी पंक्ति के रूप में लिखने की आवश्यकता होगी, जिस लाइन को आप बदलना चाहते हैं।

21

सबसे आसान तरीका है:

static void lineChanger(string newText, string fileName, int line_to_edit) 
{ 
    string[] arrLine = File.ReadAllLines(fileName); 
    arrLine[line_to_edit - 1] = newText; 
    File.WriteAllLines(fileName, arrLine); 
} 

उपयोग:

lineChanger("new content for this line" , "sample.text" , 34); 
+0

बिल्कुल शानदार जवाब !!!! ... पूरी तरह से यहां काम कर रहे। डॉट नेट 2.0 में चल रहा है ... Unity3d में यह है: ___ फ़ंक्शन लाइन परिवर्तक (नया टेक्स्ट: स्ट्रिंग, फ़ाइल नाम: स्ट्रिंग, line_to_edit: int) { var arrline: स्ट्रिंग [] = फ़ाइल। रीडअललाइन (फ़ाइल नाम); arrline [line_to_edit - 1] = newText; File.WriteAllLines (फ़ाइल नाम, arrline); } –

+0

इसमें 1 समस्या है, यह पूरी फ़ाइल को फिर से लिखता है। –

+0

यह पूरी फ़ाइल को स्मृति में एक बार में लोड करता है। लेकिन यह शायद सबसे आसान तरीका है और अभी भी छोटी फाइलों के साथ प्रयोग योग्य है। –

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