我需要在C#中从文件中读取除最后x行以外的所有内容到StreamReader中。 什么是最好的方法?
非常感谢!
非常感谢!
如果它是一个大文件,有可能只需定位到文件末尾,然后反向检查字节是否为 '\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而言。当然,有人可能会认为,如果想要删除所有行,从开头到结尾更加高效。
你不需要真正地读取一个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);
allBut = File.ReadLines(path).Reverse().Skip(5).Reverse();
什么也不做,直到你执行它(即,迭代它)。 - Anthony Pegram假设你是在提及文件中的行,那么我认为这是一个文本文件。如果你只想获取行,可以将它们读入到一个字符串数组中,如下所示:
string[] lines = File.ReadAllLines(@"C:\test.txt");
如果您确实需要使用StreamReaders:
using (StreamReader reader = new StreamReader(@"C:\test.txt"))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
StreamReader
应该足以推断出 OP 正在谈论文本。 - M.Babcock
\n
以外的任何其他内容)? - M.Babcock