从流读取器中删除最后x行

时间:2012-03-09 03:08:05

标签: c# file streamreader

我需要读取除C#中文件到流读取器的最后x行之外的所有行。这样做的最佳方式是什么?

非常感谢!

3 个答案:

答案 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.当然,如果有人想要消除所有行,可以提出这样的论点,然后从开始到结束更有效率。