c# 倒序读取txt文件
原创
©著作权归作者所有:来自51CTO博客作者xxj_jing的原创作品,请联系作者获取转载授权,否则将追究法律责任
倒序读取txt文件,基本思路:
1.使用 FileStream 文件流,可以设置流的位置 position;
2.每次读取一行:行的标记就是两个 \n 之间的内容,占位符在流中的值为 ;
byte n = 0xD;//回车符
byte r = 0xA;//换行符
3.读取时每一行从后向前读,所以输出的字符串为倒的,故读完一行后要将内容反转;
4.倒序读行时同理,行的记录也是倒的,需要将行记录反转;
调用方法:
1.获取文件夹下的所有文件信息
var files = GetFile("c:\logs");
2.获取指定文件最后200行记录
var result = LastLog("c:\\logs\log.txt",0);
result.data ;//文件内容
result.position; //本次读取流的起始位置
主要方法:
/// <summary>
/// 获取目录下所有文件信息
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private List<LogFileModel> GetFile(string path)
{
List<LogFileModel> list = new List<LogFileModel>();
var files = Directory.GetFiles(path);
if (files.IsNullOrDbNull())
return null;
LogFileModel item;
FileInfo f;
Func<long, string> getFileSize = (x) =>
{
if (x <= 0)
return "0KB";
var d = Math.Round(x*1.0/1024/1024, 2);
return string.Format("{0}KB", d);
};
var fileInfos = new List<FileInfo>();
files.All(x =>
{
fileInfos.Add(new FileInfo(x));
return true;
});
int i = 1;
//按照创建时间倒序
fileInfos
.OrderByDescending(x=>x.CreationTime)
.ToList()
.ForEach(x =>
{
item = new LogFileModel
{
name = x.Name,
size=x.Length,
desc = getFileSize(x.Length)
};
list.Add(item);
if (i++ >= 20)
return ;
});
return list;
}
/// <summary>
/// 倒序读取文本文件
/// </summary>
/// <param name="file">文件路径</param>
/// <param name="position">读取流的起始位置</param>
/// <returns></returns>
public LastLogResult LastLog(string file, long position)
{
if (!File.Exists(file))
{
result.msg = "文件路径无效!";
return result;
}
StringBuilder txt = new StringBuilder();
long ps = position;
using (var fs = new FileStream(file,FileMode.Open,FileAccess.Read))
{
if (ps <= 0)
ps = fs.Length;
//读取200行
for (int i = 0; i < 200; i++)
{
ps = InverseReadRow(fs, ps, ref txt);
if (ps <= 0)
break;
}
}
result.data = txt.ToString();
result.position = ps;
result.success = true;
return result;
}
/// <summary>
/// 从后向前按行读取文本文件,最多读取 10kb
/// </summary>
/// <param name="fs"></param>
/// <param name="position"></param>
/// <param name="s"></param>
/// <param name="maxRead">默认每次最多读取10kb数据</param>
/// <returns>返回读取位置</returns>
long InverseReadRow(FileStream fs
, long position
, ref StringBuilder s
, int maxRead = 10240)
{
byte n = 0xD;//回车符
byte r = 0xA;//换行符
if (fs.Length == 0)
return 0;
var newPos = position - 1;
int curVal = 0;
var readLength = 0;
List<byte> arr = new List<byte>();
var str = "";
//bool brk = false;
do
{
readLength++;
if (newPos <= 0)
newPos = 0;
fs.Position = newPos;
curVal = fs.ReadByte();
if (curVal == -1)
break;
arr.Insert(0, (byte)curVal);
if (newPos <= 0)
break;
//
if (readLength == maxRead)
break;
if (curVal != n)
newPos--;
} while (curVal != n);
str = Encoding.UTF8.GetString(arr.ToArray());
s.Insert(0, str);
return newPos;
}
使用的对象
public class LogFileModel
{
public string name { set; get; }
public long size { set; get; }
public string desc { set; get; }
}
public class ResultModel<T>
{
public ResultModel()
{
data = default(T);
}
public string msg { set; get; }
public bool success
{
set;
get;
}
public T data { set; get; }
}
public class LastLogResult : ResultModel<string>
{
public long position { set; get; }
}