(StreamReader.ReadLine()==null)还是(-1 != StreamReader.Peek())?

有人问到一个问题:

一个文本里有多行,如:
geafd1
bragd2
beree3
beaee4
dfefa/
fdasf5
feafd/
..
..
怎么把结尾是“/”的行删掉?

 

其实,解决思路很简单,将文本逐行读取到数组中,再遍历数组判断即可。于是,某个项目中常用方法:

方法一:

 

复制代码
public static string GetListStringDemo(string strFilePath, string bakPath, string strOld)
{
string strResult = string.Empty; ;
if (File.Exists(strFilePath))
{
try
{
#region Read
StringBuilder strBuilder
= new StringBuilder();
using (StreamReader sr = File.OpenText(strFilePath))
{
String input;
while ((input = sr.ReadLine()) != null)
{
if (!input.EndsWith(strOld))
{
strBuilder.Append(input
+ "\r\n");
}
}
}
strResult
= strBuilder.ToString();
#endregion

#region Write
System.IO.StreamWriter sw
= new System.IO.StreamWriter(bakPath);
sw.Write(strResult);
sw.Close();
#endregion
Console.WriteLine(
"OK!");
}
catch (Exception ex)
{
strResult
= "请求错误:" + ex.Message;
#region Loghandle by Tony 2010.08.18
//记录错误日志
#endregion
}
}
return strResult;
}
复制代码

 

这也是微软提供的示例,在实际使用中发现,该方法的缺陷在于某些时候不能读取完整地读取文件所有行。怀疑是缓冲区过小。查MSDN说明:

StringReader   .ReadLine 方法将行定义为后面跟有下列符号的字符序列:换行符(“\n”)、回车符(“\r”)或后跟换行符的回车符(“\r\n”)。 所产生的字符串不包含终止回车符和/或换行符。 如果已到达基础字符串的结尾,则返回值为 null  
http://msdn.microsoft.com/zh-cn/library/system.io.streamreader.readline.aspx

我的理解:如果由于编码的问题,导致读取异常,也就是无法读取行标志时,可能会认为已到文件结尾而中断下行的读取。这也解释了为什么会有时读取不完整的原因。

如何避免这个问题呢?可以使用方法二:

方法二:

复制代码
public static string GetListStringDemoWithPeek(string strFilePath, string bakPath, string strOld)
{
string strResult = string.Empty; ;
if (File.Exists(strFilePath))
{

try
{
#region Read
StringBuilder strBuilder
= new StringBuilder();
using (StreamReader sr = File.OpenText(strFilePath))
{
while (-1 != sr.Peek())// or try "sr.Peek>=0"
{
string temp = sr.ReadLine().ToString();
if (!temp.EndsWith(strOld))
{
strBuilder.Append(temp
+ "\r\n");
}
}
}
strResult
= strBuilder.ToString();
#endregion

#region Write
System.IO.StreamWriter sw
= new System.IO.StreamWriter(bakPath);
sw.Write(strResult);
sw.Close();

#endregion
Console.WriteLine(
"OK!");
}
catch (Exception ex)
{
strResult
= "请求错误:" + ex.Message;
#region Loghandle by Tony 2010.08.18
//记录错误日志
#endregion
}
}
return strResult;
}
复制代码

这里使用StreamReader的Peek()方法,依据MSDN的说明,

Peek 方法返回一个整数值以便确定是否到达文件末尾,或发生其他错误。这样一来,用户在将返回值强制转换为 Char 类型之前就可以首先检查该值是否为 -1。

换句话说,它不需要先转换字符,即可返回是否达到文件末尾。

http://msdn.microsoft.com/zh-cn/library/system.io.streamreader.peek.aspx

 

其实还可以用第三种方法:File   ReadAllLines 方法 (String)

方法三:

复制代码
public static void GetSubStringFromFile(string strFilePath, string bakPath, string strOld)
{
if (File.Exists(strFilePath))
{
string[] lst = File.ReadAllLines(strFilePath);
List
<string> st = new List<string>();
foreach (string s in lst)
{
if (!s.Contains(strOld))
{
st.Add(s);
}
}
File.WriteAllLines(bakPath, st.ToArray
<string>());
Console.WriteLine(
"OK!");
}
}
复制代码

MSDN说明:

此方法打开一个文件,读取文件的每一行,然后将每一行添加为字符串数组的一个元素。然后它关闭文件。根据定义,一行就是一个后面跟有下列符号的字符序列:回车符(“\r”)、换行符(“\n”)或回车符后紧跟一个换行符。所产生的字符串不包含终止回车符和/或换行符。

此方法尝试根据现存的字节顺序标记来自动检测文件的编码。可检测到编码格式 UTF-8 和 UTF-32(包括 big-endian 和 little-endian)。

 

http://msdn.microsoft.com/zh-cn/library/s2tte0y1.aspx

方法三也可能存在与方法一类似的缺陷。

posted @   邀月  阅读(3970)  评论(1编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
历史上的今天:
2009-08-18 VS2008无法在断点处停留的解决方案(downmoon收集)
点击右上角即可分享
微信分享提示