C# 高效提取txt文档最后一行数据

C# 高效提取txt文档最后一行数据_历史数据​ ​ 

 如题,最近在开发一个小型项目,由于数据量比较小,且无复杂的数据关系,数据量一天一个对象大概也就2~3M的大小,所以就将数据写入txt文档进行存储,如下图所示:

 

C# 高效提取txt文档最后一行数据_文件流_02

每一天的数据

C# 高效提取txt文档最后一行数据_文件流_03

6-23的数据

但在最后查询一整天的历史数据的时候,每一条数据的开始时间和结束时间分别是对应txt文档的第一行和最后一行数据里面的时间,所以在查询历史数据的时候,需要读取每一个txt文件中的第一个和最后一行,最开始我的提取方法如下:

                using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs))
{
// 读取首行
string line = sr.ReadLine();
SDataAircraft data = JsonWrapper.DeserializeObject<SDataAircraft>(line);

if (data == null)
{
sr.Close();
fs.Close();
continue;
}

info.StartTime = Convert.ToDateTime(data.timeStamp);

// 读取末行
while (!sr.EndOfStream)
{
line = sr.ReadLine();
}

....

sr.Close();
fs.Close();
}


在集成到系统时,由于某一天的历史数据大概有1000多条,所以在查询时耗时很长,长到无法忍受,看了下代码,应该是提取最后一行数据时花费较多时间,所以就优化了下代码,如所示:

                using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs))
{
// 读取首行
string line = sr.ReadLine();
SDataAircraft data = JsonWrapper.DeserializeObject<SDataAircraft>(line);

if (data == null)
{
sr.Close();
fs.Close();
continue;
}

info.StartTime = Convert.ToDateTime(data.timeStamp);

// 读取末行
line = GetLastLine(fs);

...

sr.Close();
fs.Close();


读取最后一行数据的方法如下:

    /// <summary>
/// 提取文本最后一行数据
/// </summary>
/// <param name="fs">文件流</param>
/// <returns>最后一行数据</returns>
private string GetLastLine(FileStream fs)
{
int seekLength = (int)(fs.Length < 1024 ? fs.Length : 1024); // 这里需要根据自己的数据长度进行调整,也可写成动态获取,可自己实现
byte[] buffer = new byte[seekLength];
fs.Seek(-buffer.Length, SeekOrigin.End);
fs.Read(buffer, 0, buffer.Length);
string multLine = System.Text.Encoding.UTF8.GetString(buffer);
string[] lines = multLine.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries);
string line = lines[lines.Length - 1];

return line;
}


优化后的查询耗时也就1 ~ 2秒就完成,比起之前真是快了不是一丢丢啊~

所以同志们,方法是多么重要哦。

另外,在同时读写同一个文件时,需要设置文件流的FileShare.ReadWrite

写文件

        using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine(data);
sw.Close();
fs.Close();
}


读文件

                using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs))
{
// 读取首行
string line = sr.ReadLine();
...

sr.Close();
fs.Close();
}