Как я могу прочитать текстовый файл, не блокируя его?
У меня служба 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();
}
}
Есть ли проблема в моем коде при чтении и записи?
Как решить проблему?
7 ответов
Вы должны убедиться, что и служба, и программа чтения открывают файл журнала не эксклюзивно. Попробуй это:
Для службы используйте экземпляр FileStream, созданный следующим образом:
var outStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
Для читателя используйте то же самое, но измените доступ к файлу:
var inStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
Удачи!
Явно настроить режим обмена при чтении текстового файла.
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++;
}
}
}
new StreamReader(File.Open(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
-> это не блокирует файл.
Проблема в том, что когда вы пишете в журнал, вы блокируете файл исключительно, поэтому ваш 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
}
}
}
Я помню, что делал то же самое пару лет назад. После некоторых запросов Google я нашел это:
FileStream fs = new FileStream(@”c:\test.txt”,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);
т.е. использовать атрибут FileShare.ReadWrite в FileStream ().
(найдено в блоге Баладжи Рамеша)
Вы пытались скопировать файл, а затем прочитать его?
Просто обновляйте копию всякий раз, когда делаются большие изменения.
Этот метод поможет вам быстрее всего прочитать текстовый файл и не блокировать его.
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 "";
}
}
Надеюсь, что этот метод поможет вам.