C# 读取文本文件的最后一行

C# 读取文本文件的最后一行,c#,C#,我需要知道如何读取文本文件的最后一行。我需要找到该行,然后将其处理到SQL数据库中。。。我一直在阅读和浏览网页,但我正在努力找到正确的方法来做到这一点。即: 查找文件的最后一行 处理文件的最后一行 我希望这是有意义的。有两种方法:简单而低效,或者极其复杂但高效。复杂的版本采用合理的编码 除非您的文件太大,以至于您真的负担不起全部阅读,否则我只会使用: var lastLine = File.ReadLines("file.txt").Last(); 请注意,这使用的是,而不是。如果使用.NET

我需要知道如何读取文本文件的最后一行。我需要找到该行,然后将其处理到SQL数据库中。。。我一直在阅读和浏览网页,但我正在努力找到正确的方法来做到这一点。即:

  • 查找文件的最后一行
  • 处理文件的最后一行

  • 我希望这是有意义的。

    有两种方法:简单而低效,或者极其复杂但高效。复杂的版本采用合理的编码

    除非您的文件太大,以至于您真的负担不起全部阅读,否则我只会使用:

    var lastLine = File.ReadLines("file.txt").Last();
    
    请注意,这使用的是,而不是。如果使用.NET 3.5或更早版本,则需要使用
    文件。ReadAllLines
    或编写自己的代码-
    ReadAllLines
    将一次性将整个文件读取到内存中,而
    ReadLines
    将其流式处理

    否则,复杂的方法是使用类似的代码。它尝试从文件末尾向后读取,处理诸如UTF-8多字节字符之类的不干净内容。这很不愉快。

    我会简单地组合并:

    它对行进行流式处理,不会将所有行作为
    文件加载到内存中。ReadAllLines

    第一部分:

    File.ReadAllLines(@"c:\some\path\file.txt").Last();
    


    首选读线。

    注意:所有这些代码都假定为UTF-8。如果需要支持使用双宽字符(如Unicode)的代码页,则需要在换行符之前和/或之后向字符添加额外的检查,以确保它确实是换行符

    string m = "";
    StreamReader r = new StreamReader("file_path");
    while (r.EndOfStream == false)
    {
        m = r.ReadLine();
    }
    Console.WriteLine("{0}\n", m);
    r.Close();
    
    这个问题的一个主要用例是抓取日志文件的结尾。当日志文件达到兆字节时,其他答案不幸地消失了。想象一下,在一个小小的单核VPS上运行每次呼叫的每条线路。。。哎呀

    UTF-8的好处在于,当您点击“\n”字符时,您不必担心任何依赖字节,因为UTF8-8中任何高位清除的字节都只是ASCII字符。非常方便

    您可以在“”处使用解决方案,但请注意代码相当复杂。如果您只需要一个简单的UTF-8行预告片,此解决方案将工作得非常好,即使在大型日志文件上也会表现出色

    如果您同时监视大量文件,并且在C#中使用类似FileSystemWatcher的东西,那么这种性能提升将非常重要。我在一个廉价的单cpu Linux VPS上使用非常类似的代码来监视登录失败,并在我的麻省理工学院授权项目中将ip地址放在防火墙中,使用(一次处理多个新行)

    当SSH端口面向公众时,auth.log的大小会让您大吃一惊。如果您定期阅读几十个甚至数百个文件,您会很高兴没有使用
    File.ReadAllLines().Last()

    因为这只是一页代码,所以它在简单和快速之间取得了很好的平衡

    C#代码

    //
    ///实用程序类以性能敏感的方式从utf-8文本文件中读取最后一行。该代码不处理一次写入多行的情况。
    /// 
    公共静态类UTF8FileUtilities
    {
    /// 
    ///从文件中读取最后一行。此方法假定对文件的每次写入都将以新行字符(“\n”)终止
    /// 
    ///要读取的文件的路径
    ///最后一行,如果无法读取某行(空文件或正在进行部分行写入),则为null
    ///打开或读取文件失败
    公共静态字符串ReadLastLine(字符串路径)
    {
    //以只读方式打开,我们不希望有任何写入数据的机会
    使用(System.IO.Stream fs=System.IO.File.OpenRead(path))
    {
    //检查是否有空文件
    如果(fs.Length==0)
    {
    返回null;
    }
    //从文件末尾开始
    fs.位置=fs.长度-1;
    //如果没有进行部分行写入,则文件必须以“\n”字符结尾
    int byteFromFile=fs.ReadByte();
    如果(byteFromFile!='\n')
    {
    //正在进行部分行写入,请勿返回该行
    返回null;
    }
    //移回新行字节-循环将再次递减位置,以到达它之前的字节
    财政司司长职位-;
    //虽然尚未到达文件的开头,但请向后读取字节,直到命中“\n”字节
    而(fs.Position>0)
    {
    财政司司长职位-;
    byteFromFile=fs.ReadByte();
    if(byteFromFile<0)
    {
    //发生这种情况的唯一方法是,当我们反向读取时,有人从我们下面截取文件
    抛出新System.IO.IOException(“从“+路径”处的文件读取时出错);
    }
    else if(byteFromFile=='\n')
    {
    //我们找到了新行,break out,fs。位置在“\n”字符后面
    打破
    }
    财政司司长职位-;
    }
    //fs.Position将紧跟在“\n”字符之后,如果没有“\n”字符,则位置0
    byte[]bytes=new System.IO.BinaryReader(fs.ReadBytes)((int)(fs.Length-fs.Position));
    返回System.Text.Encoding.UTF8.GetString(字节);
    }
    }
    }
    
    您尝试过什么?请注意,我们只能在“1”方面提供帮助。。。“2”完全由你决定;fs.Seek(0,SeekOrigin.End);for(long offset=0;offsetFile.ReadLines(@"c:\some\path\file.txt").Last();
    string m = "";
    StreamReader r = new StreamReader("file_path");
    while (r.EndOfStream == false)
    {
        m = r.ReadLine();
    }
    Console.WriteLine("{0}\n", m);
    r.Close();
    
    string last = File.ReadLines(@"C:\file.txt").Last();
    string lastsymbol = last[last.Count - 1];
    
    /// <summary>
    /// Utility class to read last line from a utf-8 text file in a performance sensitive way. The code does not handle a case where more than one line is written at once.
    /// </summary>
    public static class UTF8FileUtilities
    {
        /// <summary>
        /// Read the last line from the file. This method assumes that each write to the file will be terminated with a new line char ('\n')
        /// </summary>
        /// <param name="path">Path of the file to read</param>
        /// <returns>The last line or null if a line could not be read (empty file or partial line write in progress)</returns>
        /// <exception cref="Exception">Opening or reading from file fails</exception>
        public static string ReadLastLine(string path)
        {
            // open read only, we don't want any chance of writing data
            using (System.IO.Stream fs = System.IO.File.OpenRead(path))
            {
                // check for empty file
                if (fs.Length == 0)
                {
                    return null;
                }
    
                // start at end of file
                fs.Position = fs.Length - 1;
    
                // the file must end with a '\n' char, if not a partial line write is in progress
                int byteFromFile = fs.ReadByte();
                if (byteFromFile != '\n')
                {
                    // partial line write in progress, do not return the line yet
                    return null;
                }
    
                // move back to the new line byte - the loop will decrement position again to get to the byte before it
                fs.Position--;
    
                // while we have not yet reached start of file, read bytes backwards until '\n' byte is hit
                while (fs.Position > 0)
                {
                    fs.Position--;
                    byteFromFile = fs.ReadByte();
                    if (byteFromFile < 0)
                    {
                        // the only way this should happen is if someone truncates the file out from underneath us while we are reading backwards
                        throw new System.IO.IOException("Error reading from file at " + path);
                    }
                    else if (byteFromFile == '\n')
                    {
                        // we found the new line, break out, fs.Position is one after the '\n' char
                        break;
                    }
                    fs.Position--;
                }
    
                // fs.Position will be right after the '\n' char or position 0 if no '\n' char
                byte[] bytes = new System.IO.BinaryReader(fs).ReadBytes((int)(fs.Length - fs.Position));
                return System.Text.Encoding.UTF8.GetString(bytes);
            }
        }
    }