使用计时器逐行读取文本文件

时间:2018-06-30 19:24:53

标签: c# streamreader datalog

gulp.src('app/**/*.*')

问题是我正在通过GUI读取一个充满变量的文本文件,例如重播视频。如代码所示,它可以正常工作,并且我可以控制计时器刻度以更改重放速度。问题是文件正在使用中,因此在使用文件时,如果不先关闭文件,就无法写入或删除文本。我希望能够找到Streamreader的解决方法,或者使用Filestream to Streamreader代码,该代码可让我在使用文件时对其进行编辑。那里的问题是,我不知道如何使它与计时器一起使用,它只是非常快速地读取整个文件。任何帮助或想法都将不胜感激。

这里的问题是如何将注释掉的代码用于:

  1. 读取一行文本文件,
  2. 让计时器打勾
  3. 然后读取文本文件的下一行,依此类推。显然在数据到达时对其进行处理。

2 个答案:

答案 0 :(得分:4)

在使用中打开文件

我认为您要查找的是FileStream实例的FileShare.ReadWriteStreamReader,{em>(不是您已注释掉的实例),< / p>

var fs = new FileStream("C:\foo.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var sr = new StreamReader(fs);

设置流的位置

根据您的评论,您似乎在定位流时遇到了麻烦,这就是您可以执行的操作...

fs.Position = 0; // note this is the FileStream not the StreamReader!
// alternatively, you could use Seek

顺序访问和随机访问之间的区别

最后,您可能希望在下面查看一下顺序访问和随机访问之间的区别

concept


潜在的解决方案

这是一个名为FileMonitor的类,它将在文件更改/更新时检查文件并更新列表。

我了解您想让计时器轮询文本文件中的数据,但是如果计时器非常快,我已经优化了FileMonitor来监视文件的更改,并且仅在有改变。

  

请注意,这仅会根据流的位置继续读取从上次中断的地方开始的内容。因此,如果在“提取”之前删除或修改了行,它将不起作用。这意味着它只能根据您的要求运行,而不能在处理许多其他情况下进行改进,但是它应该足以满足您的要求。

public class FileMonitor : IDisposable
{
    private readonly FileStream _file;
    private readonly StreamReader _reader;

    private long _position;
    private List<string> _lines;

    public FileMonitor(string file)
    {
        if (String.IsNullOrEmpty(nameof(file))) throw new ArgumentNullException(nameof(file));

        _lines = new List<string>();

        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = Path.GetDirectoryName(file);
        watcher.Filter = Path.GetFileName(file);
        watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
        watcher.Changed += new FileSystemEventHandler(OnChanged);
        //watcher.Created += new FileSystemEventHandler(OnCreated);
        //watcher.Deleted += new FileSystemEventHandler(OnDeleted);
        //watcher.Renamed += new RenamedEventHandler(OnRenamed);

        // begin watching.
        watcher.EnableRaisingEvents = true;

        // begin reading
        _file = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        _reader = new StreamReader(_file);
        _lines = ReadLines(_reader).ToList();
        _position = _file.Position;
    }

    private void OnChanged(object source, FileSystemEventArgs e)
    {
        List<string> update = ReadLines(_reader).ToList();
         // fix to remove the immidate newline
        if (update.Count() > 0 && String.IsNullOrEmpty(update[0])) update.RemoveAt(0);
        _lines.AddRange(update);
        _position = _file.Position;

        // just for debugging, you should remove this
        Console.WriteLine($"File: {e.FullPath} [{e.ChangeType}]");
    }

    public IEnumerable<string> Lines { get { return _lines; } }

    public void Reset()
    {
        _file.Position = 0;
        _position = _file.Position;
        _lines.Clear(); 
    }

    private static IEnumerable<string> ReadLines(StreamReader reader)
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }

    public void Dispose()
    {
        _reader.Dispose();
        _file.Dispose();
    }
}

这里是如何与计时器一起使用

private IEnumerable<string> _lines; // holds all the lines "extracted"

void Main()
{
    string file = @"C:\Data\foo.txt";

    using (var timer = new System.Timers.Timer())
    {
        timer.Interval = 2000; // 2 second interval
        timer.Elapsed += OnTimedEvent; // attach delegate
        timer.Enabled = true; // start the timer    

        // open the file
        using (var monitor = new FileMonitor(file))
        {
            _lines = monitor.Lines;

             // loop forever, remove this
            while (true) { }
        }
    }
}

public void OnTimedEvent(object sender, EventArgs e)
{
    // just for debugging, you should remove this
    Console.WriteLine($"current count: {_lines.Count()}");
}

如果不清楚,提取的数据将保存在字符串列表中。在上方,您可以使用monitor.Line属性从监视器中获取“提取的”数据。

答案 1 :(得分:2)

一种行之有效的解决方案

 string line;
        if (!File.Exists(logFile))
        {
            viewLog.Text = "Play";
            alertTB.ForeColor = Color.Red;
            alertTB.Text = "File Does Not Exist | Log Data To Create File";
            chart.Text = "Scope On";
        }

        if (File.Exists(logFile))
        {
            var lineCount = File.ReadLines(logFile).Count();//read text file line count to establish length for array
            if (lineCount < 2)
            {
                viewLog.Text = "Play";
                alertTB.ForeColor = Color.Red;
                alertTB.Text = "File Exists | No Data Has Been Recorded";
                chart.Text = "Scope On";
            }

            if (counter < lineCount && lineCount > 0)//if counter is less than lineCount keep reading lines
            {
                line = File.ReadAllLines(logFile).Skip(counter).Take(lineCount).First();

                string[] dataLog = line.Split(new[] { ',' }, StringSplitOptions.None);
                //-----------------------------------------Handling my data 
                counter++;
            }
            else
            {
                counter = 0;
                timer2.Enabled = false;
            }
        }

这是我得到的修复,它允许编辑文件或删除文件内容。在尝试加载文件之前,我得到了行数。然后,我使用计数器遍历所有行。我可以根据计时器的滴答间隔更改下一行读取之间的延迟,将其暂停或停止。