잠그지 않고 텍스트 파일을 어떻게 읽을 수 있습니까?


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
   ...
}

행운을 빕니다!



완벽 함-FileAccess.Read를 사용하는 File.Open ()으로 충분하다고 생각했지만 그렇지 않습니다. 그래도 그렇습니다. :)
neminem

작가에게는 작가가 한 명뿐이므로 FileShare.Read만으로 충분하지 않습니까?
crokusek

2
또한 그 FileStream구현에 주목할 가치가 있습니다IDisposable
weeksdev

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

즉, FileStream ()에서 FileShare.ReadWrite 속성을 사용합니다.

( 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.