2014-07-24 5 views
1

내 응용 프로그램의 Windows 서비스에 FileSystemWatcher을 추가하려고합니다. 제 경우에는 연속적으로 업데이트되는 텍스트 파일이 한 줄 또는 두 줄 이상일 수 있으며 파일이 가져올 때마다 업데이트 나는 이전에 읽지 않은 모든 텍스트 파일 행을 읽을 필요가있다. FileSystemWatcher 및 텍스트 파일의 마지막 줄

나는 goolged 및 파일이 업데이트 될 때 한 번이

File.ReadText(@"C:\Filename.txt").Last(); 

나에게 TEXTFILE의 마지막 줄을 줄 것이라는 점을 알고있어하지만 난이 모든 읽지 않은 행 또는 마지막 만 제공할지 확실하지 않다 또한 textfile.Also 내 텍스트 파일을 줄 단위로 업데이트되고 있습니다.

두 경우 모두 가능한 해결책은 무엇입니까?

텍스트 파일이 한 줄씩 업데이트되는 경우 FileSystemWatcher은 파일에 추가 된 마지막 줄을 여러 번 볼 수 있습니다.

도와주세요. 코드 업데이트

.. 코드 업데이트

using (var sr = new StreamReader(@"C:\Temp\LineTest.txt")) 
{ 
    string line; 
    long pos = 0; 
    while ((line = sr.ReadLine()) != null) 
    { 
     Console.Write("{0:d3} ", pos); 
     Console.WriteLine(line); 
     pos += line.Length; 
    } 
} 

.

public partial class Service1 : ServiceBase 
{ 
    public Service1() 
    { 
     InitializeComponent(); 
    } 

    private System.Threading.Thread _thread; 
    private ManualResetEvent _shutdownEvent = new ManualResetEvent(false); 
    int lineCount; 
    long previousLength = 0; 
    string filepath = "C:\\Temp\\LineTest.txt"; 


    public void OnDebug() 
    { 

     OnStart(null); 

    } 

    protected override void OnStart(string[] args) 
    { 

     _thread = new Thread(addLogic); 
     _thread.Start(); 


    } 

    //This event is raised when a file is changed 
    private void Watcher_Changed(object sender, FileSystemEventArgs e) 
    { 
     _thread = new Thread(addlogic); 
     _thread.Start(); 
    } 


    public static string[] ReadFromFile(string filePath, int count, ref int lineCount) 
    { 
     lineCount += count; 
     return File.ReadLines(filePath).Skip(lineCount).Take(count).ToArray(); 
    } 
    public void addlogic() 
    { 
     //Add Logic Here 
     //How to use lineCount here to read specific line that i am not getting 

      //If all textfile gets traversed then is FileSystemWatcher 
      FileSystemWatcher Watcher = new FileSystemWatcher(filepath); 
      Watcher.EnableRaisingEvents = true; 
      Watcher.Changed += new FileSystemEventHandler(Watcher_Changed); 

     } 
    } 



    protected override void OnStop() 
    { 
     _shutdownEvent.Set(); 
     _thread.Join(); // wait for thread to stop 
    } 
     } 
    } 
+0

여러 행을 추가하는 경우 서비스에서 읽은 행을 추적해야합니다. 나는 너 자신을 항상 읽는 선을 추적하는 것이 좋습니다. – bansi

+0

@bansi Line은 텍스트 파일에 한 번에 하나씩 만 추가되고 있으며 또한 읽음 및 읽지 않은 행을 분리 할 수있는 행에 고유 한 부분이 없습니다. 또한 읽은 행 추적에 관해서는 어떻게 진행할 수 있는지 말해주십시오 . – user3816352

+2

마지막으로 읽은 오프셋을 저장하고 다음부터 그 위치에서 시작할 수 있습니다. – bansi

답변

2

방금 ​​추가 된 행을 읽는 간단한 클래스를 작성했습니다. 이것은 실제로 동일한 행에서도 파일에 추가되는 내용을 읽습니다.

public class AddedContentReader 
{ 

    private readonly FileStream _fileStream; 
    private readonly StreamReader _reader; 

    //Start position is from where to start reading first time. consequent read are managed by the Stream reader 
    public AddedContentReader(string fileName, long startPosition = 0) 
    { 
     //Open the file as FileStream 
     _fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
     _reader = new StreamReader(_fileStream); 
     //Set the starting position 
     _fileStream.Position = startPosition; 
    } 


    //Get the current offset. You can save this when the application exits and on next reload 
    //set startPosition to value returned by this method to start reading from that location 
    public long CurrentOffset 
    { 
     get { return _fileStream.Position; } 
    } 

    //Returns the lines added after this function was last called 
    public string GetAddedLines() 
    { 
     return _reader.ReadToEnd(); 
    } 


} 

이렇게하면됩니다.

private AddedContentReader _freader; 

protected override void OnStart(string[] args) 
{ 
    _freader = new AddedContentReader("E:\\tmp\\test.txt"); 
    //If you have saved the last position when the application did exit then you can use that value here to start from that location like the following 
    //_freader = new AddedContentReader("E:\\tmp\\test.txt",lastReadPosition); 

} 
private void Watcher_Changed(object sender, FileSystemEventArgs e) 
{ 
    string addedContent= _freader.GetAddedLines(); 
    //you can do whatever you want with the lines 
} 

참고 : 매우 빠른 업데이트로 테스트하지 않았습니다.

+0

Bansi님께 감사드립니다. 나는 서비스의 다음 시작을 위해 저장할 수있는 Windows 서비스의'Stop()'메소드에서 어떻게'public long CurrentOffset'를 호출 할 수 있는지에 대한 하나의 쿼리를 가지고 있습니다. – user3816352

+0

'protected override void OnStop()을 추가했습니다. { lastLineReadOffset = _freader.CurrentOffset; }'서비스를 종료 할 때 마지막 오프셋을 가져 오는 것입니다. 올바른 방법입니까? – user3816352

+0

네가 맞습니다. 어딘가에 저장할 수 있고 서비스가 다시 시작될 때 읽고 그 값을 사용할 수 있습니다. – bansi

2

여기 bansi가 의견에서 제안한 내용을 기반으로 한 아이디어입니다. 그것은 읽은 행의 수를 유지하고 새로운 행을 텍스트 상자에 추가합니다. 파일이 너무 커지면 다루기 힘들 수 있습니다.

private int linesProcessed; //Variable for keeping track of your line position 

private void ProcessFile(string filePath) 
{ 
    string[] lines = File.ReadAllLines(filePath); 
    if (linesProcessed != lines.Count()) //Make sure a new line was entered 
    { 
     for (int i = linesProcessed ; i < lines.Count(); i++) 
     { 
      textBox1.AppendText(lines[i] + "\n") ; 
      linesProcessed += 1; 
     } 
    } 
} 

private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e) 
{ 
    ProcessFile("c:\\temp\\test.txt"); //your file name here 
} 

은 영업 이익의 코드를 변경 수정. 메소드가 실행될 때마다 재설정되지 않도록 루프 외부에 위치 변수를 배치했습니다.

long pos = 0; 
private void ProcessFile(string filePath) 
{ 
    using (var sr = new StreamReader(filePath)) 
    { 
     string line; 

     long count = 0; 
     while ((line = sr.ReadLine()) != null) 
     { 
      count += 1; 
      if (pos < count) 
      { 
       Console.Write("{0:d3} ", pos); 
       Console.WriteLine(line); 
       pos += 1; 
      } 
     } 
    } 
} 
+0

이 경우 서비스가 중지되고 어떤 이유로 든 시작되면 카운트를 잃게됩니다. –

+0

나는 내 게시물을 업데이 트했습니다.이 코드를 사용하는 방법과 작동하는 텍스트 파일의 크기는 무엇입니까? – user3816352

+0

@EladLachmi 사실입니다. 그렇다면 응용 프로그램 외부의 카운트를 계속 유지하려고합니다. 이는 또 다른 질문입니다. –

관련 문제