C# 从streamreader中删除最后的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

我需要在C#中读取文件到streamreader的所有x行,但最后的x行除外。最好的方法是什么


非常感谢

您并没有真正读入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();
在执行它之前不会做任何事情(例如,在它上面迭代).谢谢你,我明天第一件事就是要试试,但它看起来能满足我的需要。非常感谢大家的帮助。