• (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

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

  • 相关阅读:
    「译」JVM是如何使用那些你从未听过的x86魔幻指令实现String.compareTo的
    「译」Graal JIT编译器是如何工作的
    [Inside HotSpot] C1循环不变代码提升优化
    Java逆变(Covariant)和协变(Contravariant)
    [Inside HotSpot] Xcode编译调试OpenJDK12
    [Inside HotSpot] UseParallelGC和UseParallelOldGC的区别
    [Inside HotSpot] Java分代堆
    [Inside HotSpot] Serial垃圾回收器 (二) Minor GC
    [Inside HotSpot] Epsilon GC
    [Inside HotSpot] Serial垃圾回收器 (一) Full GC
  • 原文地址:https://www.cnblogs.com/downmoon/p/1802095.html
Copyright © 2020-2023  润新知