मैं किसी पाठ फ़ाइल को बिना लॉक किए कैसे पढ़ सकता हूं?


94

मेरे पास एक विंडोज़ सेवा है जो एक सरल प्रारूप में पाठ फ़ाइल में अपना लॉग लिखती है।

अब, मैं सेवा के लॉग को पढ़ने के लिए एक छोटा एप्लिकेशन बनाने जा रहा हूं और मौजूदा लॉग और जोड़े गए दोनों को लाइव दृश्य के रूप में दिखाता है।

समस्या यह है कि सेवा नई लाइनों को जोड़ने के लिए पाठ फ़ाइल को लॉक कर देती है और उसी समय दर्शक एप्लिकेशन को पढ़ने के लिए फ़ाइल को लॉक कर देता है।

सेवा कोड:

void WriteInLog(string logFilePath, data)
{
    File.AppendAllText(logFilePath, 
                       string.Format("{0} : {1}\r\n", DateTime.Now, data));
}

दर्शक कोड:

int index = 0;
private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                using (StreamReader sr = new StreamReader(logFilePath))
                {
                    while (sr.Peek() >= 0)  // reading the old data
                    {
                        AddLineToGrid(sr.ReadLine());
                        index++;
                    }
                    sr.Close();
                }

                timer1.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


private void timer1_Tick(object sender, EventArgs e)
        {
            using (StreamReader sr = new StreamReader(logFilePath))
            {
                // skipping the old data, it has read in the Form1_Load event handler
                for (int i = 0; i < index ; i++) 
                    sr.ReadLine();

                while (sr.Peek() >= 0) // reading the live data if exists
                {
                    string str = sr.ReadLine();
                    if (str != null)
                    {
                        AddLineToGrid(str);
                        index++;
                    }
                }
                sr.Close();
            }
        }

क्या पढ़ने और लिखने के तरीके में मेरे कोड में कोई समस्या है?

इस समस्या को कैसे सुलझाया जाए?


जवाबों:


120

आपको यह सुनिश्चित करने की आवश्यकता है कि सेवा और पाठक दोनों लॉग फ़ाइल को गैर-अनन्य रूप से खोलें। इसे इस्तेमाल करे:

सेवा के लिए - आपके उदाहरण में लेखक - FileStreamनिम्नानुसार बनाई गई एक आवृत्ति का उपयोग करें :

var outStream = new FileStream(logfileName, FileMode.Open, 
                               FileAccess.Write, FileShare.ReadWrite);

पाठक उसी का उपयोग करें, लेकिन फ़ाइल का उपयोग बदलें:

var inStream = new FileStream(logfileName, FileMode.Open, 
                              FileAccess.Read, FileShare.ReadWrite);

इसके अलावा, चूंकि FileStreamलागू IDisposableकरना सुनिश्चित करता है कि दोनों मामलों में आप usingलेखक के लिए एक उदाहरण का उपयोग करने पर विचार करते हैं :

using(var outStream = ...)
{
   // using outStream here
   ...
}

सौभाग्य!


वहाँ भी ReadLines () संस्करण है पर stackoverflow.com/questions/5338450/...
कॉलिन

बिल्कुल सही - मैंने सोचा था कि FileOpen () FileAccess के साथ। पर्याप्त था, लेकिन यह नहीं है। हालांकि यह है। :)
नीमनेम

लेखक पर, FileShare.Read पर्याप्त नहीं होगा क्योंकि केवल एक ही लेखक है?
क्रोकेक

2
इसके अलावा, लायक यह देखते हुए कि FileStreamऔजारIDisposable
weeksdev

28

टेक्स्ट फ़ाइल को पढ़ते समय शेयरिंग मोड को स्पष्ट करें।

using (FileStream fs = new FileStream(logFilePath, 
                                      FileMode.Open, 
                                      FileAccess.Read,    
                                      FileShare.ReadWrite))
{
    using (StreamReader sr = new StreamReader(fs))
    {
        while (sr.Peek() >= 0) // reading the old data
        {
           AddLineToGrid(sr.ReadLine());
           index++;
        }
    }
}

2
स्ट्रीमरैडर के रूप में स्ट्रीम को स्पष्ट रूप से बंद करना अनावश्यक है। प्रस्ताव इसे स्वचालित रूप से बंद कर देता है।
नॉट्रो

2
मेरा मानना ​​है कि फ़ाइल शेयर को बीओटीएच पर पढ़ा जाना चाहिए और स्ट्रीम लिखना चाहिए, और न केवल पढ़ना।
LEO

अगर मैं गलत नहीं हूँ, तो FileReader.Dispose भी FileStream को डिस्पोज़ करता है। यहां इसका दो बार निस्तारण किया गया।
एग्रीगेट

12
new StreamReader(File.Open(logFilePath, 
                           FileMode.Open, 
                           FileAccess.Read, 
                           FileShare.ReadWrite))

-> यह फ़ाइल को लॉक नहीं करता है।


1
डेटा पढ़ने पर काम करने लगता है। जब बंद फ़ाइल त्रुटि लेखन आता है।
9

8

समस्या यह है कि जब आप लॉग को लिख रहे हैं तो आप विशेष रूप से फ़ाइल को बंद कर रहे हैं ताकि आपके स्ट्रीमराइडर को इसे खोलने की अनुमति न हो।

आप में फ़ाइल खोलने की कोशिश करने की जरूरत है केवल पढ़ने के लिए मोड।

using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (StreamReader sr = new StreamReader(fs))
    {
        while (!fs.EndOfStream)
        {
            string line = fs.ReadLine();
            // Your code here
        }
    }
}

जैसा कि अब मुझे पता है, File.ReadAllText()केवल पढ़ने के लिए मोड के साथ विफल रहता है।
bohdan_trotsenko

@modosansreves हाँ, मैंने उत्तर के उस भाग को डॉक्स स्थिति के रूप में हटा दिया है कि UnauthorizedAccessExceptionअगर फ़ाइल केवल पढ़ने के लिए है , तो वह फेंक देगा - उत्तर देने के समय चूक गया होगा!
जेम्स

5

मुझे कुछ साल पहले वही काम करना याद है। कुछ Google प्रश्नों के बाद मुझे यह मिला:

    FileStream fs = new FileStream(@”c:\test.txt”, 
                                   FileMode.Open, 
                                   FileAccess.Read,        
                                   FileShare.ReadWrite);

यानी FileStream पर FileShare.ReadWrite विशेषता का उपयोग करें।

( बालाजी रमेश के ब्लॉग पर पाया गया )


1

क्या आपने फ़ाइल को कॉपी करने की कोशिश की है, फिर उसे पढ़ रहे हैं?

जब भी बड़े बदलाव किए जाएं तो कॉपी को अपडेट करें।


2
मैंने यह कोशिश की है और यह सबसे अच्छा समाधान नहीं है। फ़ाइल को कॉपी करने में बहुत लंबा समय लगता है, 4mb फ़ाइल के लिए 20 सेकंड का समय लगता है।
सीची

-1

यह विधि आपको पाठ फ़ाइल को सबसे तेज़ी से पढ़ने और लॉक किए बिना मदद करेगी।

private string ReadFileAndFetchStringInSingleLine(string file)
    {
        StringBuilder sb;
        try
        {
            sb = new StringBuilder();
            using (FileStream fs = File.Open(file, FileMode.Open))
            {
                using (BufferedStream bs = new BufferedStream(fs))
                {
                    using (StreamReader sr = new StreamReader(bs))
                    {
                        string str;
                        while ((str = sr.ReadLine()) != null)
                        {
                            sb.Append(str);
                        }
                    }
                }
            }
            return sb.ToString();
        }
        catch (Exception ex)
        {
            return "";
        }
    }

आशा है कि यह विधि आपकी मदद करेगी।


1
जहां तक ​​मैं समझता हूं, यह विधि एक पूरी फाइल को एक स्ट्रिंग में पढ़ती है और रास्ते में अपवादों को निगल जाती है। मैं यह नहीं देख सकता कि फ़ाइल लॉकिंग में मदद करना कैसा है।
डिफ़ॉल्ट लोकेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.