Mam usługę Windows zapisującą swój dziennik w pliku tekstowym w prostym formacie.
Teraz utworzę małą aplikację, która odczyta dziennik usługi i pokaże zarówno istniejący, jak i dodany dziennik jako podgląd na żywo.
Problem polega na tym, że usługa blokuje plik tekstowy do dodawania nowych wierszy, a jednocześnie aplikacja przeglądarki blokuje plik do odczytu.
Kod serwisowy:
void WriteInLog(string logFilePath, data)
{
File.AppendAllText(logFilePath,
string.Format("{0} : {1}\r\n", DateTime.Now, data));
}
Kod przeglądarki:
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();
}
}
Czy jest jakiś problem w moim kodzie podczas czytania i pisania?
Jak rozwiązać problem?
Odpowiedzi:
Musisz upewnić się, że zarówno usługa, jak i czytnik otwierają plik dziennika niewyłącznie. Spróbuj tego:
Dla usługi - writer w twoim przykładzie - użyj
FileStream
instancji utworzonej w następujący sposób:var outStream = new FileStream(logfileName, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
Dla czytelnika użyj tego samego, ale zmień dostęp do pliku:
var inStream = new FileStream(logfileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Ponadto, ponieważ
FileStream
implementuje,IDisposable
upewnij się, że w obu przypadkach rozważasz użycieusing
instrukcji, na przykład dla pisarza:using(var outStream = ...) { // using outStream here ... }
Powodzenia!
źródło
FileStream
implementujeIDisposable
Jawne skonfigurowanie trybu udostępniania podczas czytania pliku tekstowego.
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++; } } }
źródło
new StreamReader(File.Open(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
-> to nie blokuje pliku.
źródło
Problem polega na tym, że kiedy piszesz do dziennika, blokujesz plik wyłącznie, aby StreamReader nie mógł go w ogóle otworzyć.
Musisz spróbować otworzyć plik w trybie tylko do odczytu .
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 } } }
źródło
File.ReadAllText()
nie działa w trybie tylko do odczytu.UnauthorizedAccessException
jeśli plik jest tylko do odczytu - musiałem to przegapić w momencie odpowiadania!Pamiętam, jak robiłem to samo kilka lat temu. Po kilku zapytaniach w Google znalazłem to:
FileStream fs = new FileStream(@”c:\test.txt”, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
tj. użyj atrybutu FileShare.ReadWrite w FileStream ().
(znalezione na blogu Balaji Ramesh )
źródło
Czy próbowałeś skopiować plik, a następnie go przeczytać?
Wystarczy zaktualizować kopię, gdy zostaną wprowadzone duże zmiany.
źródło
Ta metoda pomoże Ci szybciej odczytać plik tekstowy i bez blokowania go.
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 ""; } }
Mam nadzieję, że ta metoda ci pomoże.
źródło