我需要读取除C#中文件到流读取器的最后x行之外的所有行。这样做的最佳方式是什么?
非常感谢!
答案 0 :(得分:3)
你真的没有读过INTO的StreamReader。事实上,对于您要求的模式,根本不需要StreamReader。 System.IO.File具有有用的静态方法'ReadLines',您可以使用它:
IEnumerable<string> allBut = File.ReadLines(path).Reverse().Skip(5).Reverse();
之前有缺陷的版本,回应评论帖子
List<string> allLines = File.ReadLines(path).ToList();
IEnumerable<string> allBut = allLines.Take(allLines.Count - 5);
答案 1 :(得分:3)
由于你指的是文件中的行,我假设它是一个文本文件。如果你只想获得这些行,你可以将它们读成一个字符串数组,如下所示:
string[] lines = File.ReadAllLines(@"C:\test.txt");
或者如果你真的需要使用StreamReaders:
using (StreamReader reader = new StreamReader(@"C:\test.txt"))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
答案 2 :(得分:3)
如果它是一个大文件,是否可以只搜索到文件的末尾,并检查'\ n'字符的反向字节?我知道\ n和\ r \ n存在。我掀起了以下代码并在一个相当简单的文件上进行了测试。你能尝试在你拥有的文件上测试吗?我知道我的解决方案看起来很长,但我认为你会发现它比从头开始读取并重写整个文件更快。
public static void Truncate(string file, int lines)
{
using (FileStream fs = File.Open(file, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
fs.Position = fs.Length;
// \n \r\n (both uses \n for lines)
const int BUFFER_SIZE = 2048;
// Start at the end until # lines have been encountered, record the position, then truncate the file
long currentPosition = fs.Position;
int linesProcessed = 0;
byte[] buffer = new byte[BUFFER_SIZE];
while (linesProcessed < linesToTruncate && currentPosition > 0)
{
int bytesRead = FillBuffer(buffer, fs);
// We now have a buffer containing the later contents of the file
for (int i = bytesRead - 1; i >= 0; i--)
{
currentPosition--;
if (buffer[i] == '\n')
{
linesProcessed++;
if (linesProcessed == linesToTruncate)
break;
}
}
}
// Truncate the file
fs.SetLength(currentPosition);
}
}
private static int FillBuffer(byte[] buffer, FileStream fs)
{
if (fs.Position == 0)
return 0;
int bytesRead = 0;
int currentByteOffset = 0;
// Calculate how many bytes of the buffer can be filled (remember that we're going in reverse)
long expectedBytesToRead = (fs.Position < buffer.Length) ? fs.Position : buffer.Length;
fs.Position -= expectedBytesToRead;
while (bytesRead < expectedBytesToRead)
{
bytesRead += fs.Read(buffer, currentByteOffset, buffer.Length - bytesRead);
currentByteOffset += bytesRead;
}
// We have to reset the position again because we moved the reader forward;
fs.Position -= bytesRead;
return bytesRead;
}
由于你只打算删除文件的末尾,所以重写所有内容似乎都很浪费,特别是如果它是一个大文件和小N.当然,如果有人想要消除所有行,可以提出这样的论点,然后从开始到结束更有效率。