C# 读取文本文件的最后一行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11625595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Read last line of text file
提问by Debbie Dippenaar
I need to know how to read the last line of a text file. I need to find the line and then process it into a SQL database... I've been reading around and scouring the web but am battling to find the proper way to do this. I.e.:
我需要知道如何读取文本文件的最后一行。我需要找到该行,然后将其处理到 SQL 数据库中...我一直在阅读和搜索网络,但我正在努力寻找正确的方法来做到这一点。IE:
- Find last line of file.
- Process last line of file.
- 找到文件的最后一行。
- 处理文件的最后一行。
I hope this makes sense.
我希望这是有道理的。
回答by Jon Skeet
There are two ways: simple and inefficient, or horrendously complicated but efficient. The complicated version assumes a sane encoding.
有两种方法:简单而低效,或极其复杂但有效。复杂的版本假设一个健全的编码。
Unless your file is sobig that you really can't afford to read it all, I'd just use:
除非你的文件是如此之大,你真的可以读不起这一切,我只是用:
var lastLine = File.ReadLines("file.txt").Last();
Note that this uses File.ReadLines, notFile.ReadAllLines. If you're using .NET 3.5 or earlier you'd need to use File.ReadAllLinesor write your own code - ReadAllLineswill read the wholefile into memory in one go, whereas ReadLinesstreams it.
请注意,这使用File.ReadLines,而不是File.ReadAllLines. 如果您使用 .NET 3.5 或更早版本,则需要使用File.ReadAllLines或编写自己的代码 -ReadAllLines将一次性将整个文件读入内存,而ReadLines将其流式传输。
Otherwise, the complicated way is to use code similar to this. It tries to read backwards from the end of the file, handling nastiness such as UTF-8 multi-byte characters. It's not pleasant.
否则,复杂的方法是使用类似于this 的代码。它尝试从文件末尾向后读取,处理诸如 UTF-8 多字节字符之类的肮脏问题。这并不愉快。
回答by Tim Schmelter
I would simply combine File.ReadLines(path)and Enumerable.Last:
我会简单地结合File.ReadLines(path)和Enumerable.Last:
String last = File.ReadLines(@"C:\file.txt").Last();
It streams the lines and does not load all into memory as File.ReadAllLines.
它流式传输行并且不会将所有内容加载到内存中File.ReadAllLines。
回答by juFo
First part:
第一部分:
File.ReadAllLines(@"c:\some\path\file.txt").Last();
or
或者
File.ReadLines(@"c:\some\path\file.txt").Last();
ReadLines is prefered.
ReadLines 是首选。
回答by krish
string m = "";
StreamReader r = new StreamReader("file_path");
while (r.EndOfStream == false)
{
m = r.ReadLine();
}
Console.WriteLine("{0}\n", m);
r.Close();
回答by luuk
string last = File.ReadLines(@"C:\file.txt").Last();
string lastsymbol = last[last.Count - 1];
回答by jjxtra
Note: All this code assumes UTF-8. If you need to support a code page that uses double wide chars like Unicode, then you need to add extra checks to the char before and/or after the newline to make sure it is really a newline.
注意:所有这些代码都假定为 UTF-8。如果您需要支持使用双宽字符(如 Unicode)的代码页,那么您需要在换行符之前和/或之后对字符添加额外检查,以确保它确实是换行符。
One of the primary use cases of this question is scraping the end of a log file. The other answers unfortunately die a horrible death when log files get into the megabytes. Imagine running every line on every call on a tiny single core VPS... yikes.
此问题的主要用例之一是抓取日志文件的末尾。不幸的是,当日志文件达到兆字节时,其他答案会死得很惨。想象一下,在一个很小的单核 VPS 上运行每次通话的每一行……哎呀。
The nice thing about UTF-8 is that when you hit a '\n' character, you don't have to worry about any dependent bytes because any byte with the high bit clear in UTF8-8 is simply an ASCII character. Pretty handy!
UTF-8 的好处在于,当您遇到 '\n' 字符时,您不必担心任何相关字节,因为 UTF8-8 中任何具有高位清除的字节都只是一个 ASCII 字符。很方便!
You could use the solution at 'How to read a text file reversely with iterator in C#', but be aware that the code is fairly complex. If you just need a simple UTF-8 line trailer, this solution will work very well and perform great even on large log files.
您可以使用“如何使用C# 中的迭代器反向读取文本文件”中的解决方案,但请注意,代码相当复杂。如果您只需要一个简单的 UTF-8 行预告片,此解决方案将非常有效,即使在大型日志文件上也能表现出色。
If you are monitoring lots of files at once and are using something like a FileSystemWatcher in C#, this performance gain will be very important. I am using very similar code on a cheap single cpu Linux VPS to monitor login failures and put ip addresses in the firewall in my MIT licensed project https://github.com/DigitalRuby/IPBan, using https://github.com/DigitalRuby/IPBan/blob/master/Core/IPBanLogFileScanner.cs(which handles multiple new lines at once).
如果您一次监视大量文件并使用 C# 中的 FileSystemWatcher 之类的东西,那么这种性能提升将非常重要。我在廉价的单 CPU Linux VPS 上使用非常相似的代码来监视登录失败并将 IP 地址放入我的 MIT 许可项目https://github.com/DigitalRuby/IPBan的防火墙中,使用https://github.com/ DigitalRuby/IPBan/blob/master/Core/IPBanLogFileScanner.cs(一次处理多个新行)。
You'd be suprised at how large auth.log can get when your SSH port is public facing. Yes, a VPN, I know... :)
当您的 SSH 端口面向公众时,您会对 auth.log 的大小感到惊讶。是的,VPN,我知道... :)
C# Code ...
C# 代码...
/// <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 UTF8FileLastLineReader
{
/// <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 ReadLastLineFromUTF8EncodedFile(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);
}
}
}

