我需要知道如何阅读文本文件的最后一行。我需要找到该行,然后将其处理成一个SQL数据库...我一直在阅读并搜索网络,但我正在努力找到正确的方法来做到这一点。即:
我希望这是有道理的。
答案 0 :(得分:60)
有两种方式:简单和低效,或者非常复杂但有效。复杂的版本采用合理的编码。
除非您的文件如此大,否则您真的无法全部阅读,我只会使用:
var lastLine = File.ReadLines("file.txt").Last();
请注意,这会使用File.ReadLines
,而不是 File.ReadAllLines
。如果您使用的是.NET 3.5或更早版本,则需要使用File.ReadAllLines
或编写自己的代码 - ReadAllLines
将整个文件一次性读入内存,而ReadLines
则会传播它。
否则,复杂的方法是使用类似于this的代码。它尝试从文件末尾向后读取,处理诸如UTF-8多字节字符之类的恶意。这不愉快。
答案 1 :(得分:9)
我只想合并File.ReadLines(path)
和Enumerable.Last
:
String last = File.ReadLines(@"C:\file.txt").Last();
它会对行进行流式处理,而不会将所有内容作为File.ReadAllLines
加载到内存中。
答案 2 :(得分:9)
第一部分:
File.ReadAllLines(@"c:\some\path\file.txt").Last();
或
File.ReadLines(@"c:\some\path\file.txt").Last();
首选ReadLines。
答案 3 :(得分:6)
string m = "";
StreamReader r = new StreamReader("file_path");
while (r.EndOfStream == false)
{
m = r.ReadLine();
}
Console.WriteLine("{0}\n", m);
r.Close();
答案 4 :(得分:3)
注意:所有这些代码都假定为UTF-8。如果您需要支持使用Unicode等双宽字符的代码页,那么您需要在换行符之前和/或之后为char添加额外的检查,以确保它真的是换行符。
此问题的主要用例之一是抓取日志文件的末尾。不幸的是,当日志文件进入兆字节时,其他答案会死得很可怕。想象一下,在一个微小的单核VPS上,每次通话都会运行每一行......哎呀。
关于UTF-8的好处是当你点击'\ n'字符时,你不必担心任何相关字节,因为UTF8-8中任何高位清除的字节都只是一个ASCII字符。非常方便!
您可以使用“How to read a text file reversely with iterator in C#”的解决方案,但要注意代码相当复杂。如果您只需要一个简单的UTF-8线路预告片,这个解决方案将非常好用,即使在大型日志文件上也能表现出色。
如果您一次监视大量文件并在C#中使用类似FileSystemWatcher的东西,那么这种性能提升将非常重要。我在廉价的单CPU Linux VPS上使用非常相似的代码来监控登录失败,并使用https://github.com/DigitalRuby/IPBan(一次处理多个新行)在我的MIT许可项目https://github.com/DigitalRuby/IPBan/blob/master/Core/IPBanLogFileScanner.cs中将IP地址放入防火墙
当您的SSH端口面向公共端口时,您会惊讶于auth.log的大小。是的,VPN,我知道......:)
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);
}
}
}
答案 5 :(得分:-1)
import Control.Monad (liftM2)
liftM2 (==) [x,y] [2,3]
[False,False,False,True]