C# 阅读课文的最后两行
我是新手,正在开发一个应用程序,在文本文件的最后两行显示两个日期的时差 我想从文件文本中读取前最后一行,我已经知道如何读取最后一行,但我需要读取前最后一行 这是我的代码:C# 阅读课文的最后两行,c#,C#,我是新手,正在开发一个应用程序,在文本文件的最后两行显示两个日期的时差 我想从文件文本中读取前最后一行,我已经知道如何读取最后一行,但我需要读取前最后一行 这是我的代码: var lastLine = File.ReadAllLines("C:\\test.log").Last(); richTextBox1.Text = lastLine.ToString(); 你可以试着这样做 var lastLines = File.ReadAllLines("C:\\t
var lastLine = File.ReadAllLines("C:\\test.log").Last();
richTextBox1.Text = lastLine.ToString();
你可以试着这样做
var lastLines = File.ReadAllLines("C:\\test.log").Reverse().Take(2).Reverse();
但是,根据文件的大小,可能有比一次读取所有行更有效的方法来处理这个问题。查看和只需将
ReadAllLines
的结果存储到一个变量,然后取最后两个:
var allText = File.ReadAllLines("C:\\test.log");
var lastLines = allText.Skip(allText.Length - 2);
您可以像这样使用Skip()
和Take()
var lastLine = File.ReadAllLines("C:\\test.log");
var data = lastLine.Skip(lastLine.Length - 2);
richTextBox1.Text = lastLine.ToString();
您可以将StreamReader
与Queue
组合使用,因为您必须以任何一种方式读取整个文件
// if you want to read more lines change this to the ammount of lines you want
const int LINES_KEPT = 2;
Queue<string> meQueue = new Queue<string>();
using ( StreamReader reader = new StreamReader(File.OpenRead("C:\\test.log")) )
{
string line = string.Empty;
while ( ( line = reader.ReadLine() ) != null )
{
if ( meQueue.Count == LINES_KEPT )
meQueue.Dequeue();
meQueue.Enqueue(line);
}
}
使用File.ReadAllLines
将读取全文,然后使用Linq
将遍历已存在的红线。此方法在一次运行中完成所有操作。自
File.ReadAllLines("C:\\test.log");
返回一个数组,您可以获取该数组的最后两项:
var data = File.ReadAllLines("C:\\test.log");
string last = data[data.Length - 1];
string lastButOne = data[data.Length - 2];
在一般情况下,对于长文件(这就是为什么ReadAllLines
是一个错误的选择),您可以实现
public static partial class EnumerableExtensions {
public static IEnumerable<T> Tail<T>(this IEnumerable<T> source, int count) {
if (null == source)
throw new ArgumentNullException("source");
else if (count < 0)
throw new ArgumentOutOfRangeException("count");
else if (0 == count)
yield break;
Queue<T> queue = new Queue<T>(count + 1);
foreach (var item in source) {
queue.Enqueue(item);
if (queue.Count > count)
queue.Dequeue();
}
foreach (var item in queue)
yield return item;
}
}
在返回请求的最后一行之前,前面的所有答案都急切地将所有文件加载到内存中。如果文件很大,这可能是一个问题。幸运的是,这很容易避免
public static IEnumerable<string> ReadLastLines(string path, int count)
{
if (count < 1)
return Enumerable.Empty<string>();
var queue = new Queue<string>(count);
foreach (var line in File.ReadLines(path))
{
if (queue.Count == count)
queue.Dequeue();
queue.Enqueue(line);
}
return queue;
}
公共静态IEnumerable ReadLastLines(字符串路径,int计数)
{
如果(计数<1)
返回可枚举的.Empty();
var queue=新队列(计数);
foreach(File.ReadLines(路径)中的var行)
{
if(queue.Count==Count)
queue.Dequeue();
排队。排队(行);
}
返回队列;
}
这只会将最后的n
读取行保留在内存中,以避免大文件的内存问题。您的Take
是多余的,因为跳过后您知道您只剩下2个项目。请反转while文件,取两个元素并再次反转?对我来说似乎很奇怪,但应该有用。第二种相反的方法只有在你关心行的顺序时才需要,从她的问题描述中猜测可能没有必要,但只是为了给出一个完整的答案,我包括了它。你仍然必须迭代所有行,这对于大型文件来说效率很低。请参阅我答案中的链接问题。@Staeff当然可以,但它的效率比实际将整个文件加载到内存中要高出几个数量级,而这正是基于ReadAllLines
的其他解决方案所做的。@in-between,但仍然使用StreamReader
将比我在回答中所说的效率更高。当您只需要最后两行时加载整个文件是没有意义的。@m.rogalski我在哪里加载整个文件ReadLines
生成一个IEnumerable
,只要文件中有一行,它就会简单地吐出下一行。无论如何,您的解决方案和我的完全相同,很抱歉我没有阅读过去的StreamReader
,因为它不是必需的,ReadLines
也同样有效。@。我想这是像其他答案一样的ReadAllLines
。
string line;
string[] lines = new string[]{"",""};
int index = 0;
using ( StreamReader reader = new StreamReader(File.OpenRead("C:\\test.log")) )
{
while ( ( line = reader.ReadLine() ) != null )
{
lines[index] = line;
index = 1-index;
}
}
// Last Line -1 = lines[index]
// Last line = lines[1-index]
var lastTwolines = File
.ReadLines("C:\\test.log") // Not all lines
.Tail(2);
public static IEnumerable<string> ReadLastLines(string path, int count)
{
if (count < 1)
return Enumerable.Empty<string>();
var queue = new Queue<string>(count);
foreach (var line in File.ReadLines(path))
{
if (queue.Count == count)
queue.Dequeue();
queue.Enqueue(line);
}
return queue;
}
string line;
string[] lines = new string[]{"",""};
int index = 0;
using ( StreamReader reader = new StreamReader(File.OpenRead("C:\\test.log")) )
{
while ( ( line = reader.ReadLine() ) != null )
{
lines[index] = line;
index = 1-index;
}
}
// Last Line -1 = lines[index]
// Last line = lines[1-index]