Bagaimana cara membaca file teks tanpa menguncinya?

95

Saya memiliki layanan windows menulis log-nya dalam file teks dalam format sederhana.

Sekarang, saya akan membuat aplikasi kecil untuk membaca log layanan dan menampilkan log yang ada dan yang ditambahkan sebagai tampilan langsung.

Masalahnya adalah layanan mengunci file teks untuk menambahkan baris baru dan pada saat yang sama aplikasi penampil mengunci file untuk dibaca.

Kode Layanan:

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

Kode Penampil:

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

Apakah ada masalah dalam kode saya dalam membaca dan menulis?

Bagaimana cara mengatasi masalah tersebut?

Homam
sumber

Jawaban:

122

Anda perlu memastikan bahwa layanan dan pembaca membuka file log secara non-eksklusif. Coba ini:

Untuk layanan - penulis dalam contoh Anda - gunakan FileStreaminstance yang dibuat sebagai berikut:

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

Untuk pembaca gunakan yang sama tetapi ubah akses file:

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

Juga, karena FileStreampenerapan IDisposablepastikan bahwa dalam kedua kasus Anda mempertimbangkan untuk menggunakan usingpernyataan, misalnya untuk penulis:

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

Semoga berhasil!

Manfred
sumber
Ada juga versi ReadLines () di stackoverflow.com/questions/5338450/…
Colin
Sempurna - Saya pikir File.Open () dengan FileAccess.Read sudah cukup, tetapi ternyata tidak. Ini memang benar. :)
neminem
Mengenai penulis, bukankah FileShare.Read cukup karena hanya ada satu penulis?
crokusek
2
Juga, perlu dicatat bahwa FileStreammengimplementasikanIDisposable
weeksdev
28

Atur mode berbagi secara eksplisit saat membaca file teks.

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++;
        }
    }
}
kepala5150
sumber
2
tidak perlu menutup aliran secara eksplisit, karena StreamReader.Dispose menutupnya secara otomatis.
nothrow
2
Saya yakin berbagi file harus diatur pada aliran baca dan tulis KEDUA, dan tidak hanya membaca.
LEO
StreamReader.Dispose juga membuang FileStream jika saya tidak salah. Ini dibuang dua kali.
Eregrith
12
new StreamReader(File.Open(logFilePath, 
                           FileMode.Open, 
                           FileAccess.Read, 
                           FileShare.ReadWrite))

-> ini tidak mengunci file.

nothrow
sumber
1
Sepertinya berfungsi saat membaca data. Saat menulis kesalahan file terkunci muncul.
webzy
8

Masalahnya adalah ketika Anda menulis ke log Anda secara eksklusif mengunci file tersebut sehingga StreamReader Anda tidak akan diizinkan untuk membukanya sama sekali.

Anda perlu mencoba membuka file dalam mode hanya baca .

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
        }
    }
}
James
sumber
Seperti yang saya tahu, File.ReadAllText()gagal dengan mode hanya-baca.
bohdan_trotsenko
@modosansreves ya saya menghapus bagian jawaban itu karena dokumen menyatakan bahwa itu akan melempar UnauthorizedAccessExceptionjika file hanya baca - pasti melewatkannya pada saat menjawab!
Yakobus
5

Saya ingat melakukan hal yang sama beberapa tahun lalu. Setelah beberapa pertanyaan google saya menemukan ini:

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

yaitu menggunakan atribut FileShare.ReadWrite di FileStream ().

(ditemukan di blog Balaji Ramesh )

dotmartin
sumber
1

Sudahkah Anda mencoba menyalin file, lalu membacanya?

Cukup perbarui salinan setiap kali ada perubahan besar.

Tom Gullen
sumber
2
Saya sudah mencoba ini dan ini bukan solusi terbaik. Menyalin file terlalu lama, untuk file 4mb membutuhkan waktu 20 detik.
Seichi
-1

Metode ini akan membantu Anda membaca file teks tercepat dan tanpa menguncinya.

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 "";
        }
    }

Semoga metode ini bisa membantu Anda.

Amit Kumawat
sumber
1
Sejauh yang saya pahami, metode ini membaca seluruh file menjadi string dan menelan pengecualian di sepanjang jalan. Saya tidak bisa melihat bagaimana itu bisa membantu penguncian file.
lokal default