C# 如何读取文本文件而不锁定它?

C# 如何读取文本文件而不锁定它?,c#,file-io,C#,File Io,我有一个windows服务以简单的格式将其日志写入文本文件 现在,我将创建一个小应用程序来读取服务日志,并将现有日志和添加的日志显示为实时视图 问题是服务会锁定文本文件以添加新行,同时查看器应用程序会锁定文件以进行读取 服务代码: void WriteInLog(string logFilePath, data) { File.AppendAllText(logFilePath, string.Format("{0} : {1}\r\n",

我有一个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();
            }
        }
int索引=0;
私有void Form1\u加载(对象发送方、事件参数e)
{
尝试
{
使用(StreamReader sr=新StreamReader(logFilePath))
{
while(sr.Peek()>=0)//读取旧数据
{
AddLineToGrid(sr.ReadLine());
索引++;
}
高级关闭();
}
timer1.Start();
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message);
}
}
私有无效计时器1_刻度(对象发送方,事件参数e)
{
使用(StreamReader sr=新StreamReader(logFilePath))
{
//跳过旧数据,它已读入Form1\u加载事件处理程序
对于(int i=0;i=0)//读取实时数据(如果存在)
{
字符串str=sr.ReadLine();
如果(str!=null)
{
AddLineToGrid(str);
索引++;
}
}
高级关闭();
}
}
我的代码在读写方面有什么问题吗


如何解决这个问题?

您是否尝试过复制文件,然后读取它


只要在进行重大更改时更新副本即可。

您是否尝试过复制文件,然后读取它


只要在进行重大更改时更新副本。

问题在于,当您写入日志时,您以独占方式锁定了文件,因此根本不允许您的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
        }
    }
}

问题是,当您写入日志时,您以独占方式锁定了文件,因此根本不允许您的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
        }
    }
}

显式设置读取文本文件时的共享模式

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

显式设置读取文本文件时的共享模式

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

您需要确保服务和读取器都以非独占方式打开日志文件。试试这个:

对于服务(示例中的编写器),请使用创建如下的
FileStream
实例:

var outStream=new FileStream(logfileName,FileMode.Open,
FileAccess.Write,FileShare.ReadWrite);
对于读卡器,请使用相同的,但更改文件访问权限:

var inStream=newfilestream(logfileName,FileMode.Open,
FileAccess.Read,FileShare.ReadWrite);
也可以,因为<代码>文件安全> <代码>实现<代码> IDISPOSTABLE >确保在这两种情况下都考虑使用<代码>使用语句,例如对于作者:

使用(变量扩展=…)
{
//在这里使用外流
...
}

祝你好运

您需要确保服务和读卡器都以非独占方式打开日志文件。试试这个:

new StreamReader(File.Open(logFilePath, 
                           FileMode.Open, 
                           FileAccess.Read, 
                           FileShare.ReadWrite))
对于服务(示例中的编写器),请使用创建如下的
FileStream
实例:

var outStream=new FileStream(logfileName,FileMode.Open,
FileAccess.Write,FileShare.ReadWrite);
对于读卡器,请使用相同的,但更改文件访问权限:

var inStream=newfilestream(logfileName,FileMode.Open,
FileAccess.Read,FileShare.ReadWrite);
也可以,因为<代码>文件安全> <代码>实现<代码> IDISPOSTABLE >确保在这两种情况下都考虑使用<代码>使用语句,例如对于作者:

使用(变量扩展=…)
{
//在这里使用外流
...
}
祝你好运

new StreamReader(File.Open(logFilePath, 
                           FileMode.Open, 
                           FileAccess.Read, 
                           FileShare.ReadWrite))
->这不会锁定文件


->这不会锁定文件。

我记得几年前做过同样的事情。在一些谷歌查询之后,我发现:

    FileStream fs = new FileStream(@”c:\test.txt”, 
                                   FileMode.Open, 
                                   FileAccess.Read,        
                                   FileShare.ReadWrite);
i、 e.在FileStream()上使用FileShare.ReadWrite属性


(发现于)

我记得几年前做过同样的事情。在一些谷歌查询之后,我发现:

    FileStream fs = new FileStream(@”c:\test.txt”, 
                                   FileMode.Open, 
                                   FileAccess.Read,        
                                   FileShare.ReadWrite);
i、 e.在FileStream()上使用FileShare.ReadWrite属性


(在上找到)

此方法将帮助您以最快的速度读取文本文件,而无需锁定它

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

希望此方法对您有所帮助。

此方法将帮助您以最快的速度读取文本文件,而无需锁定它

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

希望此方法能对您有所帮助。

没有必要显式关闭流,因为StreamReader.Dispose会自动关闭它。我认为应该在读流和写流上设置文件共享,如果我没有弄错的话,不仅仅是read.StreamReader.Dispose还会处理文件流。这里它被释放了两次。没有必要显式关闭流,因为StreamReader.Dispose会自动关闭它。我认为应该在读流和写流上都设置文件共享,如果我没有弄错的话,不仅read.StreamReader.Dispose还会处理文件流。这里它被处理了两次。现在我知道,
File.ReadAllText()
在只读模式下失败。@modosansreves是的,我删除了答案的这一部分,因为如果该文件是只读的,它将抛出一个
UnauthorizedAccessException
,在回答时肯定错过了这一点!现在我知道,
File.ReadAllText(