Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 覆盖StreamReader';s读线法_C#_Streamreader - Fatal编程技术网

C# 覆盖StreamReader';s读线法

C# 覆盖StreamReader';s读线法,c#,streamreader,C#,Streamreader,我正试图覆盖StreamReader的ReadLine方法,但由于无法访问某些私有变量,所以很难覆盖。这是可能的,还是我应该编写自己的StreamReader类?假设您希望自定义StreamReader可以在任何可以使用TextReader的地方使用,通常有两个选项 从StreamReader继承并重写希望以不同方式工作的函数。在您的情况下,这将是StreamReader.ReadLine 从TextReader继承并根据您的需求完全实现阅读器功能 注意:对于上面的选项2,您可以维护对Strea

我正试图覆盖StreamReader的ReadLine方法,但由于无法访问某些私有变量,所以很难覆盖。这是可能的,还是我应该编写自己的StreamReader类?

假设您希望自定义StreamReader可以在任何可以使用TextReader的地方使用,通常有两个选项

  • 从StreamReader继承并重写希望以不同方式工作的函数。在您的情况下,这将是StreamReader.ReadLine

  • 从TextReader继承并根据您的需求完全实现阅读器功能

  • 注意:对于上面的选项2,您可以维护对StreamReader实例的内部引用,并将所有功能委托给内部实例,但要替换的功能除外。在我看来,这只是选项2的一个实现细节,而不是第三个选项

    基于您的问题,我假设您已经尝试了选项1,并发现重写StreamReader.ReadLine相当困难,因为您无法访问类的内部。对于StreamReader来说,您很幸运,可以实现这一点,而无需访问StreamReader的内部实现

    下面是一个简单的例子:

    免责声明:
    ReadLine()
    实现仅用于演示目的,并不打算成为健壮或完整的实现

    class CustomStreamReader : StreamReader
    {
      public CustomStreamReader(Stream stream)
        : base(stream)
      {
      }
    
      public override string ReadLine()
      {
        int c;
    
        c = Read();
        if (c == -1)
        {
          return null;
        }
    
        StringBuilder sb = new StringBuilder();
        do
        {
          char ch = (char)c;
          if (ch == ',')
          {
            return sb.ToString();
          }
          else
          {
            sb.Append(ch);
          }
        } while ((c = Read()) != -1);
        return sb.ToString();
      }
    }
    
    您会注意到,我只是使用StreamReader.Read()方法从流中读取字符。虽然与直接使用内部缓冲区相比,绝对没有共振峰那么明显,但是
    Read()
    方法确实使用了内部缓冲区,因此仍然应该产生相当好的性能,但这需要测试以确认

    为了好玩,这里有一个选项2的示例。我使用封装的StreamReader来减少实际代码,这根本没有经过测试

    class EncapsulatedReader : TextReader
    {
      private StreamReader _reader;
    
      public EncapsulatedReader(Stream stream)
      {
        _reader = new StreamReader(stream);      
      }
    
      public Stream BaseStream
      {
        get
        {
          return _reader.BaseStream;
        }
      }
    
      public override string ReadLine()
      {
        int c;
    
        c = Read();
        if (c == -1)
        {
          return null;
        }
        StringBuilder sb = new StringBuilder();
        do
        {
          char ch = (char)c;
          if (ch == ',')
          {
            return sb.ToString();
          }
          else
          {
            sb.Append(ch);
          }
        } while ((c = Read()) != -1);
        return sb.ToString();
      }
    
      protected override void Dispose(bool disposing)
      {
        if (disposing)
        {
          _reader.Close();
        }
        base.Dispose(disposing);
      }
    
      public override int Peek()
      {
        return _reader.Peek();
      }
    
      public override int Read()
      {
        return _reader.Read();
      }
    
      public override int Read(char[] buffer, int index, int count)
      {
        return _reader.Read(buffer, index, count);
      }
    
      public override int ReadBlock(char[] buffer, int index, int count)
      {
        return _reader.ReadBlock(buffer, index, count);
      }
    
      public override string ReadToEnd()
      {
        return _reader.ReadToEnd();
      }
    
      public override void Close()
      {
        _reader.Close();
        base.Close();
      }
    }
    

    假设您希望自定义StreamReader可以在任何可以使用TextReader的地方使用,通常有两个选项

  • 从StreamReader继承并重写希望以不同方式工作的函数。在您的情况下,这将是StreamReader.ReadLine

  • 从TextReader继承并根据您的需求完全实现阅读器功能

  • 注意:对于上面的选项2,您可以维护对StreamReader实例的内部引用,并将所有功能委托给内部实例,但要替换的功能除外。在我看来,这只是选项2的一个实现细节,而不是第三个选项

    基于您的问题,我假设您已经尝试了选项1,并发现重写StreamReader.ReadLine相当困难,因为您无法访问类的内部。对于StreamReader来说,您很幸运,可以实现这一点,而无需访问StreamReader的内部实现

    下面是一个简单的例子:

    免责声明:
    ReadLine()
    实现仅用于演示目的,并不打算成为健壮或完整的实现

    class CustomStreamReader : StreamReader
    {
      public CustomStreamReader(Stream stream)
        : base(stream)
      {
      }
    
      public override string ReadLine()
      {
        int c;
    
        c = Read();
        if (c == -1)
        {
          return null;
        }
    
        StringBuilder sb = new StringBuilder();
        do
        {
          char ch = (char)c;
          if (ch == ',')
          {
            return sb.ToString();
          }
          else
          {
            sb.Append(ch);
          }
        } while ((c = Read()) != -1);
        return sb.ToString();
      }
    }
    
    您会注意到,我只是使用StreamReader.Read()方法从流中读取字符。虽然与直接使用内部缓冲区相比,绝对没有共振峰那么明显,但是
    Read()
    方法确实使用了内部缓冲区,因此仍然应该产生相当好的性能,但这需要测试以确认

    为了好玩,这里有一个选项2的示例。我使用封装的StreamReader来减少实际代码,这根本没有经过测试

    class EncapsulatedReader : TextReader
    {
      private StreamReader _reader;
    
      public EncapsulatedReader(Stream stream)
      {
        _reader = new StreamReader(stream);      
      }
    
      public Stream BaseStream
      {
        get
        {
          return _reader.BaseStream;
        }
      }
    
      public override string ReadLine()
      {
        int c;
    
        c = Read();
        if (c == -1)
        {
          return null;
        }
        StringBuilder sb = new StringBuilder();
        do
        {
          char ch = (char)c;
          if (ch == ',')
          {
            return sb.ToString();
          }
          else
          {
            sb.Append(ch);
          }
        } while ((c = Read()) != -1);
        return sb.ToString();
      }
    
      protected override void Dispose(bool disposing)
      {
        if (disposing)
        {
          _reader.Close();
        }
        base.Dispose(disposing);
      }
    
      public override int Peek()
      {
        return _reader.Peek();
      }
    
      public override int Read()
      {
        return _reader.Read();
      }
    
      public override int Read(char[] buffer, int index, int count)
      {
        return _reader.Read(buffer, index, count);
      }
    
      public override int ReadBlock(char[] buffer, int index, int count)
      {
        return _reader.ReadBlock(buffer, index, count);
      }
    
      public override string ReadToEnd()
      {
        return _reader.ReadToEnd();
      }
    
      public override void Close()
      {
        _reader.Close();
        base.Close();
      }
    }
    

    这门课可以帮助你

    public class MyStreamReader : System.IO.StreamReader
    {
        public MyStreamReader(string path)
            : base(path)
        {
    
        }
        public override string ReadLine()
        {
            string result = string.Empty;
            int b = base.Read();
            while ((b != (int)',') && (b > 0))
            {
                result += this.CurrentEncoding.GetString(new byte[] { (byte)b });
                b = base.Read();
            }
            return result;
        }
    }
    

    这门课可以帮助你

    public class MyStreamReader : System.IO.StreamReader
    {
        public MyStreamReader(string path)
            : base(path)
        {
    
        }
        public override string ReadLine()
        {
            string result = string.Empty;
            int b = base.Read();
            while ((b != (int)',') && (b > 0))
            {
                result += this.CurrentEncoding.GetString(new byte[] { (byte)b });
                b = base.Read();
            }
            return result;
        }
    }
    

    试试这个,我写这个是因为我有一些非常大的“|”分隔文件,\r\n在某些列中,我需要使用\r\n作为行的结尾分隔符。我试图使用SSIS包导入一些文件,但由于文件中的一些损坏数据,我无法导入。该文件超过5 GB,因此太大,无法打开并手动修复。我通过浏览许多论坛来了解流是如何工作的,并最终找到了一个解决方案,该解决方案读取文件中的每个字符,并根据我添加到其中的定义吐出行。这是在命令行应用程序中使用的,附带帮助:)。我希望这能帮助其他人,我还没有找到一个像其他地方一样的解决方案,尽管这些想法是受这个论坛和其他论坛的启发。这不会修复文件,它只会分割文件。。。请注意,这仍在进行中:)

    班级计划 { 静态长文件位置=0; 静态void Main(字符串[]参数) { //检查传入的信息 if(args.Any()) { 如果(参数[0]=“/?”) { var message=“将文件拆分为更小的部分”; 消息+=“\n”; 消息+=“\n”; 消息+=“拆分文件[sourceFileName][destinationFileName][RowBatchAmount][FirstRowHashHeader]”; 消息+=“\n”; 消息+=“\n”; 消息+=“[sourceFileName](字符串)必需”; 消息+=“\n”; 消息+=“[destinationFileName](字符串)将默认为与sourceFileName相同的位置”; 消息+=“\n”; 消息+=“[RowBatchAmount](INT)将创建包含这么多行的文件”; 消息+=“\n”; 消息+=“[FirstRowHashHeader](真/假)将向每个新文件添加标题行”; 控制台写入线(消息); } 其他的 { 字符串sourceFileName=args[0]; 字符串destFileLocation=args.Cou