ฉันจะอ่านไฟล์ข้อความโดยไม่ล็อคได้อย่างไร


95

ฉันมีบริการ windows เขียนบันทึกในไฟล์ข้อความในรูปแบบง่ายๆ

ตอนนี้ฉันจะสร้างแอปพลิเคชันขนาดเล็กเพื่ออ่านบันทึกของบริการและแสดงทั้งบันทึกที่มีอยู่และบันทึกที่เพิ่มเป็นมุมมองสด

ปัญหาคือบริการล็อกไฟล์ข้อความสำหรับการเพิ่มบรรทัดใหม่และในขณะเดียวกันแอ็พพลิเคชันวิวเวอร์จะล็อกไฟล์เพื่ออ่าน

รหัสบริการ:

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();
            }
        }

มีปัญหาในการอ่านและเขียนโค้ดของฉันหรือไม่?

จะแก้ปัญหาอย่างไร?


คำตอบ:


122

คุณต้องตรวจสอบให้แน่ใจว่าทั้งบริการและโปรแกรมอ่านเปิดไฟล์บันทึกโดยไม่ได้เปิดเฉพาะ ลองสิ่งนี้:

สำหรับบริการ - ผู้เขียนในตัวอย่างของคุณ - ใช้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/…
Colin

สมบูรณ์แบบ - ฉันคิดว่า File.Open () ด้วย FileAccess.Read ก็เพียงพอแล้ว แต่มันไม่ใช่ นี่คือแม้ว่า :)
neminem

สำหรับนักเขียนจะไม่ FileShare อ่านเพียงพอเนื่องจากมีนักเขียนเพียงคนเดียว?
crokusek

2
นอกจากนี้ที่น่าสังเกตว่าFileStreamการดำเนินการIDisposable
สัปดาห์ที่

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
ไม่จำเป็นต้องปิดสตรีมอย่างชัดเจนเนื่องจาก StreamReader Dispose จะปิดโดยอัตโนมัติ
nothrow

2
ฉันเชื่อว่าควรตั้งค่าการแชร์ไฟล์บนสตรีมทั้งอ่านและเขียนไม่ใช่อ่านอย่างเดียว
LEO

StreamReader.Dispose ยังทิ้ง FileStream ถ้าฉันไม่เข้าใจผิด ที่นี่ถูกกำจัดสองครั้ง
Eregrith

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

-> ไม่ได้ล็อกไฟล์


1
ดูเหมือนจะทำงานเมื่ออ่านข้อมูล เมื่อเขียนข้อผิดพลาดไฟล์ที่ถูกล็อกปรากฏขึ้น
webzy

8

ปัญหาคือเมื่อคุณเขียนลงในบันทึกคุณจะล็อกไฟล์โดยเฉพาะดังนั้น StreamReader ของคุณจะไม่ได้รับอนุญาตให้เปิดเลย

คุณต้องลองเปิดไฟล์ในโหมดอ่านอย่างเดียว

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ถ้าไฟล์เป็นแบบอ่านอย่างเดียว - ต้องพลาดในขณะที่ตอบ!
James

5

ฉันจำได้ว่าทำแบบเดียวกันเมื่อสองสามปีก่อน หลังจากคำค้นหาของ Google ฉันพบสิ่งนี้:

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

คือใช้แอตทริบิวต์ FileShare.ReadWrite บน FileStream ()

(พบในบล็อกของ Balaji Ramesh )


1

คุณได้ลองคัดลอกไฟล์แล้วอ่านหรือไม่?

เพียงอัปเดตสำเนาทุกครั้งที่มีการเปลี่ยนแปลงครั้งใหญ่


2
ฉันได้ลองแล้วและไม่ใช่วิธีแก้ปัญหาที่ดีที่สุด การคัดลอกไฟล์ใช้เวลานานเกินไปสำหรับไฟล์ 4mb ใช้เวลาประมาณ 20 วินาที
Seichi

-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
เท่าที่ฉันเข้าใจวิธีนี้จะอ่านไฟล์ทั้งหมดเป็นสตริงและกลืนข้อยกเว้นไปพร้อมกัน ฉันไม่เห็นว่ามันควรจะช่วยในการล็อกไฟล์ได้อย่างไร
ภาษาเริ่มต้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.