C# 从streamreader中删除最后的x行
我需要在C#中读取文件到streamreader的所有x行,但最后的x行除外。最好的方法是什么C# 从streamreader中删除最后的x行,c#,file,streamreader,C#,File,Streamreader,我需要在C#中读取文件到streamreader的所有x行,但最后的x行除外。最好的方法是什么 非常感谢 您并没有真正读入StreamReader。事实上,对于您所要求的模式,您根本不需要StreamReader。System.IO.File具有有用的静态方法“ReadLines”,您可以使用该方法: IEnumerable<string> allBut = File.ReadLines(path).Reverse().Skip(5).Reverse(); IEnumerable
非常感谢 您并没有真正读入StreamReader。事实上,对于您所要求的模式,您根本不需要StreamReader。System.IO.File具有有用的静态方法“ReadLines”,您可以使用该方法:
IEnumerable<string> allBut = File.ReadLines(path).Reverse().Skip(5).Reverse();
IEnumerable allBut=File.ReadLines(path).Reverse().Skip(5).Reverse();
上一个有缺陷的版本,回复评论线程
List<string> allLines = File.ReadLines(path).ToList();
IEnumerable<string> allBut = allLines.Take(allLines.Count - 5);
List allLines=File.ReadLines(path.ToList();
IEnumerable allBut=allLines.Take(allLines.Count-5);
因为您引用的是文件中的行,所以我假设它是一个文本文件。如果只想获取行,可以将它们读入字符串数组,如下所示:
string[] lines = File.ReadAllLines(@"C:\test.txt");
或者,如果您确实需要使用StreamReaders:
using (StreamReader reader = new StreamReader(@"C:\test.txt"))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
如果是一个大文件,是否可以只搜索到文件的末尾,并反向检查字节中的“\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;
}
publicstaticvoidtruncate(字符串文件,int行)
{
使用(FileStream fs=File.Open(File,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None))
{
fs.位置=fs.长度;
//\n\r\n(两个都用于行)
const int BUFFER_SIZE=2048;
//从末尾开始,直到遇到#行,记录位置,然后截断文件
长电流位置=fs.位置;
int linesProcessed=0;
字节[]缓冲区=新字节[缓冲区大小];
而(linesProcessed0)
{
int bytesRead=FillBuffer(buffer,fs);
//我们现在有了一个缓冲区,其中包含文件的后续内容
对于(int i=bytesRead-1;i>=0;i--)
{
当前位置--;
如果(缓冲区[i]='\n')
{
linesProcessed++;
if(linesProcessed==linesToTruncate)
打破
}
}
}
//截断文件
fs.设置长度(当前位置);
}
}
私有静态int FillBuffer(字节[]缓冲区,FileStream fs)
{
如果(fs.Position==0)
返回0;
int字节读取=0;
int currentByteOffset=0;
//计算可以填充多少字节的缓冲区(请记住,我们是反向的)
long expectedBytesToRead=(fs.Position
由于您只打算删除文件的结尾,重写所有内容似乎是浪费时间,特别是如果文件很大,N很小。当然,如果有人想删除所有行,然后从开头到结尾更有效。从文件末尾读取x个换行符,然后从文件开头读取到该位置。您计划从文件中读取的记录是否有某种一致性(通用记录长度,除了以
\n
结尾以外的任何内容)?使用StreamReader
应该足以假设OP是在谈论文本。我想我不确定问问题的人是否知道他们需要一个StreamReader,或者只是知道他们需要阅读一个文件,然后在网上快速搜索并看到StreamReader出现。但是,是的,你是对的,你建议读取整个文件作为性能替代方案(ReadLines.Count将读取整个文件)?你是对的。我只是做了一些定时测试。第二种方法始终更快。谢谢更新我的答案以删除第一个选项。这取决于文件长度。如果文件不适合你的空闲内存,你就完蛋了。我们需要从明显缺席的询问者那里知道他是否打算将文件(减去最后5行)读入某个内容,在这种情况下,我们已经承担了内存需求,在这种情况下,这是一个非常好的答案,或者他想逐行处理文件(当然,除了你的5艘船),在这种情况下,M.Babcock的原始注释是最正确的解决方案;通过向后读取设置标记,然后前后处理,直到达到标记。我很怀疑您正在运行有效的测试。毫无疑问,您是否在没有附加调试程序的发布模式下运行,等等,我将首先询问您是否实际上是在具体化查询结果吗?例如,allBut=File.ReadLines(path).Reverse().Skip(5).Reverse();
在执行它之前不会做任何事情(例如,在它上面迭代).谢谢你,我明天第一件事就是要试试,但它看起来能满足我的需要。非常感谢大家的帮助。