C# 读出文本文件最后50行的内容 如题。请尽可能详细些。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 private string getLast50() { string strSol=string.Empty; List<string> listFile=new List<string>(); StreamReader objSr =new StreamReader(@"c:\ss.txt",Encoding.Default); while(!objSr.EndOfStream){ listFile.Add(objSr.ReadLine()); } if(listFile.Count>50) { for (int i = listFile.Count - 50; i < listFile.Count-1; i++) { strSol+=listFile[i]+Environment.NewLine; } }else for(int i=0;i<listFile.Count;i++) { strSol+=listFile[i]+Environment.NewLine; } return strSol + listFile[listFile.Count-1]; } List<string>命名空间?不好意思;操作C#不久。同时:我用的是VS2005;Encoding.Default 类型编码好像有点问题。初充一下:我的文本文件可能达10或100M。比如一个大型的聊天室;又不想占用数据库资源。暂时解决的方法是直接存在TXT文档中。最好的是能从最后一行读取到倒数50行你的这个是直接将整个文件存放于数组中是么?这样会不会因为文件太大而出现问题? 对1楼的程序的修改: private string getLast50() { string strSol=string.Empty; List<string> listFile=new List<string>(); StreamReader objSr =new StreamReader(@"c:\ss.txt",Encoding.Default); while(!objSr.EndOfStream){ listFile.Add(objSr.ReadLine()); if ( listFile.Count > 50 ) // 如果多于50行,就把最前面的一行删掉 listFile.RemoveAt(0); } for(int i=0;i<listFile.Count;i++) { strSol+=listFile[i]+Environment.NewLine; } return strSol + listFile[listFile.Count-1]; } 这种方式做聊天室你很快就会崩溃的。用个本地的sql express也行啊。 二进制方式读取,seek到最后往前缓冲区长度的地方,读到缓冲区,分析里面有多少换行符,不够的话,往前seek 思路被VMM说了参考如下代码:FileStream vFileStream = new FileStream(@"c:\temp\temp.log", FileMode.Open, FileAccess.Read);byte[] vBuffer = new byte[0x1000];int vReadLength;int vLineCount = 0;int vReadCount = 0;int j = 0;do{ vFileStream.Seek(-vBuffer.Length * ++vReadCount, SeekOrigin.End); vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length); for (int i = vReadLength - 1; i >= 0; i--) { j++; if (vBuffer[i] == 10) vLineCount++; if (vLineCount >= 9) { if (vReadCount > 1) { vBuffer = new byte[vFileStream.Length - j - 1]; vFileStream.Seek(j, SeekOrigin.End); vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length); j = 0; } textBox1.Text = Encoding.Default.GetString(vBuffer, vReadLength - j, j); break; } }} while (vLineCount < 50 || vReadLength < vBuffer.Length);if (vLineCount < 50) textBox1.Text = Encoding.Default.GetString(vBuffer, 0, vReadLength);vFileStream.Close();Text = vLineCount.ToString();"Encoding.Default 类型编码好像有点问题"你的确认文本文件是什么编码先。 不是没想过:数据库现在要清理日志。ACCESS用的话;考虑到数据不会自动变小。也是个问题。 string[] lines = File.ReadAllLines("C:\\test.txt", System.Text.Encoding.Default);//编码看你情况而定 List<string> last50 = new List<string>();//也可以ArrayList last50=new ArrayList(); for (int i = lines.Length - 1; i >= lines.Length - 50 && i >= 0; i--) last50.Insert(0, lines[i]); --------------------------------------Access 可以压缩的 思路给你, 一行一行的全读出来,一行一行的倒序保存在List中(也就是总是在index=0的地方插入下一行内容)然后在List类中删除掉50行以后的内容,再依次读出来ArrayList类可以实现 可以。last.Add(0, lines[i]);就是从最后一个往上加。 顺道说一句:11楼的;当时的错是:vFileStream.Seek(-vBuffer.Length * ++vReadCount, SeekOrigin.End);提示操作在文本之前了;忘了具体的;大约是说:在文本内容之外了。 嗯,如果文本文件小于4096字节会出现楼主说的情况!是个bug原理10楼已经说过了,实现细节一部分要自己查MSDN啥也不说了,再贴个优化后的代码:using System.IO;/// <summary>/// 读取文本文件最后的内容/// </summary>/// <param name="AFileName">文件名</param>/// <param name="ALineCount">行数</param>/// <param name="AEncoding">字符编码</param>/// <returns>返回读取的内容</returns>public string ReadLastLine(string AFileName, int ALineCount, Encoding AEncoding){ if (ALineCount <= 0) return string.Empty; if (!File.Exists(AFileName)) return string.Empty; // 文件不存在 if (AEncoding == null) AEncoding = Encoding.Default; using (FileStream vFileStream = new FileStream(AFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (vFileStream.Length <= 0) return string.Empty; // 空文件 byte[] vBuffer = new byte[0x1000]; // 缓冲区 int vReadLength; // 读取到的大小 int vLineCount = 0; // 读取的行数 int vReadCount = 0; // 读取的次数 int vScanCount = 0; // 扫描过的字符数 long vOffset = 0; // 向后读取的位置 do { vOffset = vBuffer.Length * ++vReadCount; int vSpace = 0; // 偏移超出的空间 if (vOffset >= vFileStream.Length) // 超出范围 { vSpace = (int)(vOffset - vFileStream.Length); vOffset = vFileStream.Length; } vFileStream.Seek(-vOffset, SeekOrigin.End); //“SeekOrigin.End”反方向偏移读取位置 vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length - vSpace); #region 所读的缓冲里有多少行 for (int i = vReadLength - 1; i >= 0; i--) { if (vBuffer[i] == 10) { if (vScanCount > 0) vLineCount++; // #13#10为回车换行 if (vLineCount >= ALineCount) break; } vScanCount++; } #endregion 所读的缓冲里有多少行 } while (vReadLength >= vBuffer.Length && vOffset < vFileStream.Length && vLineCount < ALineCount); if (vReadCount > 1) // 读的次数超过一次,则需重分配缓冲区 { vBuffer = new byte[vScanCount]; vFileStream.Seek(-vScanCount, SeekOrigin.End); vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length); } return AEncoding.GetString(vBuffer, vReadLength - vScanCount, vScanCount); }}private void button1_Click(object sender, EventArgs e){ textBox1.Text = ReadLastLine(@"c:\temp\WindowsUpdate.log", 7, Encoding.Default);}对于小于1M的文件,基本不会感觉不出差别什么时候文件上10M\100M了,回头再看看帖已结,没分接了。 if (vBuffer[i] == 10) vLineCount++;char[10]换行符. VS2010出现加载不正确的情况 一道简单的面试题,谁能帮我分析下结果是如何产生的 关于c# web开发中 变量赋值后的问题 虚心请教下dataset有关使用 解决即送50分,十分满意就再加50分,各位请进来看看!~ xml读取分析 如何用循环出来后的字符串作比较?新手在等!(不敢下班) 实现类似outlook界面的程序(左右分开,左边导航,右边显示),谁有? 怎么样在C#中传送和接收一个文件?? 有关DataSet的操作? 如何用C#实现复制粘贴? 新春送吉祥,两手都要抓,一软一硬:)
{
string strSol=string.Empty;
List<string> listFile=new List<string>();
StreamReader objSr =new StreamReader(@"c:\ss.txt",Encoding.Default);
while(!objSr.EndOfStream){
listFile.Add(objSr.ReadLine());
}
if(listFile.Count>50)
{
for (int i = listFile.Count - 50; i < listFile.Count-1; i++)
{
strSol+=listFile[i]+Environment.NewLine;
}
}else
for(int i=0;i<listFile.Count;i++)
{
strSol+=listFile[i]+Environment.NewLine;
}
return strSol + listFile[listFile.Count-1];
}
List<string>命名空间?不好意思;操作C#不久。同时:我用的是VS2005;Encoding.Default 类型编码好像有点问题。
初充一下:
我的文本文件可能达10或100M。比如一个大型的聊天室;又不想占用数据库资源。
暂时解决的方法是直接存在TXT文档中。
最好的是能从最后一行读取到倒数50行你的这个是直接将整个文件存放于数组中是么?这样会不会因为文件太大而出现问题?
{
string strSol=string.Empty;
List<string> listFile=new List<string>();
StreamReader objSr =new StreamReader(@"c:\ss.txt",Encoding.Default);
while(!objSr.EndOfStream){
listFile.Add(objSr.ReadLine());
if ( listFile.Count > 50 ) // 如果多于50行,就把最前面的一行删掉
listFile.RemoveAt(0);
} for(int i=0;i<listFile.Count;i++)
{
strSol+=listFile[i]+Environment.NewLine;
}
return strSol + listFile[listFile.Count-1];
}
参考如下代码:
FileStream vFileStream = new FileStream(@"c:\temp\temp.log",
FileMode.Open, FileAccess.Read);
byte[] vBuffer = new byte[0x1000];
int vReadLength;
int vLineCount = 0;
int vReadCount = 0;
int j = 0;
do
{
vFileStream.Seek(-vBuffer.Length * ++vReadCount, SeekOrigin.End);
vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length);
for (int i = vReadLength - 1; i >= 0; i--)
{
j++;
if (vBuffer[i] == 10) vLineCount++;
if (vLineCount >= 9)
{
if (vReadCount > 1)
{
vBuffer = new byte[vFileStream.Length - j - 1];
vFileStream.Seek(j, SeekOrigin.End);
vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length);
j = 0;
}
textBox1.Text = Encoding.Default.GetString(vBuffer,
vReadLength - j, j);
break;
}
}
} while (vLineCount < 50 || vReadLength < vBuffer.Length);
if (vLineCount < 50)
textBox1.Text = Encoding.Default.GetString(vBuffer, 0, vReadLength);
vFileStream.Close();
Text = vLineCount.ToString();"Encoding.Default 类型编码好像有点问题"你的确认文本文件是什么编码先。
数据库现在要清理日志。
ACCESS用的话;考虑到数据不会自动变小。也是个问题。
string[] lines = File.ReadAllLines("C:\\test.txt", System.Text.Encoding.Default);//编码看你情况而定
List<string> last50 = new List<string>();//也可以ArrayList last50=new ArrayList();
for (int i = lines.Length - 1; i >= lines.Length - 50 && i >= 0; i--)
last50.Insert(0, lines[i]);
Access 可以压缩的
然后在List类中删除掉50行以后的内容,再依次读出来ArrayList类可以实现
可以。
last.Add(0, lines[i]);就是从最后一个往上加。
11楼的;当时的错是:vFileStream.Seek(-vBuffer.Length * ++vReadCount, SeekOrigin.End);
提示操作在文本之前了;忘了具体的;大约是说:在文本内容之外了。
原理10楼已经说过了,实现细节一部分要自己查MSDN啥也不说了,再贴个优化后的代码:
using System.IO;/// <summary>
/// 读取文本文件最后的内容
/// </summary>
/// <param name="AFileName">文件名</param>
/// <param name="ALineCount">行数</param>
/// <param name="AEncoding">字符编码</param>
/// <returns>返回读取的内容</returns>
public string ReadLastLine(string AFileName, int ALineCount, Encoding AEncoding)
{
if (ALineCount <= 0) return string.Empty;
if (!File.Exists(AFileName)) return string.Empty; // 文件不存在
if (AEncoding == null) AEncoding = Encoding.Default;
using (FileStream vFileStream = new FileStream(AFileName,
FileMode.Open, FileAccess.Read, FileShare.Read))
{ if (vFileStream.Length <= 0) return string.Empty; // 空文件
byte[] vBuffer = new byte[0x1000]; // 缓冲区
int vReadLength; // 读取到的大小
int vLineCount = 0; // 读取的行数
int vReadCount = 0; // 读取的次数
int vScanCount = 0; // 扫描过的字符数
long vOffset = 0; // 向后读取的位置
do
{
vOffset = vBuffer.Length * ++vReadCount;
int vSpace = 0; // 偏移超出的空间
if (vOffset >= vFileStream.Length) // 超出范围
{
vSpace = (int)(vOffset - vFileStream.Length);
vOffset = vFileStream.Length;
}
vFileStream.Seek(-vOffset, SeekOrigin.End); //“SeekOrigin.End”反方向偏移读取位置 vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length - vSpace);
#region 所读的缓冲里有多少行
for (int i = vReadLength - 1; i >= 0; i--)
{
if (vBuffer[i] == 10)
{
if (vScanCount > 0) vLineCount++; // #13#10为回车换行
if (vLineCount >= ALineCount) break;
}
vScanCount++;
}
#endregion 所读的缓冲里有多少行
} while (vReadLength >= vBuffer.Length && vOffset < vFileStream.Length &&
vLineCount < ALineCount); if (vReadCount > 1) // 读的次数超过一次,则需重分配缓冲区
{
vBuffer = new byte[vScanCount];
vFileStream.Seek(-vScanCount, SeekOrigin.End);
vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length);
}
return AEncoding.GetString(vBuffer, vReadLength - vScanCount, vScanCount);
}
}private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = ReadLastLine(@"c:\temp\WindowsUpdate.log", 7, Encoding.Default);
}对于小于1M的文件,基本不会感觉不出差别
什么时候文件上10M\100M了,回头再看看帖已结,没分接了。
char[10]换行符.