在c#中读取一行而不修剪行分隔符

时间:2010-02-06 23:28:58

标签: c# string newline trim

我有一个我想逐行阅读的字符串,但我还需要有行分隔符字符,但不幸的是,它修剪了StringReader.ReadLine(与保存它的ruby不同)。什么是实现这一目标的最快和最强大的方法?

我一直在考虑的替代方案:

  • 逐个字符读取输入并每次检查行分隔符
  • 使用RegExp.Split,具有正向前瞻

或者我只关心行分隔符,因为我需要知道字符串中的实际位置,分隔符可以是一个或多个字符长。因此,如果我能够取回光标在字符串中的实际位置也会很好,但StringReader没有这个功能。

编辑:这是我目前的实施。通过返回空字符串来指定文件结尾。

StringBuilder line = new StringBuilder();
int r = _input.Read();
while (r >= 0)
{
  char c = Convert.ToChar(r);
  line.Append(c);
  if (c == '\n') break;
  if (c == '\r')
  {
    int peek = _input.Peek();
    if (peek == -1) break;
    if (Convert.ToChar(peek) != '\n') break;
  }
  r = _input.Read();
}
return line.ToString();

4 个答案:

答案 0 :(得分:2)

您是否担心文件(即来自Unix / Mac与Windows)或文件内的不一致?

如果您知道单个文件与本身一致,那么一个非常简单的优化就是只逐个字符地读取第一行并找出分隔符是什么。然后确定任何其他线的确切位置将是简单的数学。

如果做不到这一点,我想我会按照逐个字符的路线行事。正则表达式似乎太“聪明”。这听起来像一个复杂的功能,我认为最重要的是让它易于编写,阅读,理解,最重要的是调试。


还有另一种方法可以做到这一点,如果您的数据源是流,则会更有效。不幸的是,正如你的评论中提到的那样,你不得不首先创建一个;但是,无论如何我都会包含解决方案,它可能会给你一些灵感:

public IEnumerable<int> GetLineStartIndices(string s)
{
    yield return 0;
    byte[] chars = Encoding.UTF8.GetBytes(s);
    using (MemoryStream stream = new MemoryStream(chars))
    {
        using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
        {
            while (reader.ReadLine() != null)
            {
                yield return stream.Position;
            }
        }
    }
}

这将返回每个新行的开始位置。显然你可以调整它来做任何你需要的事情,即用你读过的实际行做其他事情。

请注意,这必须复制字符串以创建字节数组,因此它实际上不适合非常大的字符串。它比char-by-char方法更好一点,更容易出错,所以如果字符串不是兆字节长,也许值得考虑。

答案 1 :(得分:0)

如果您只关心这个位置:ReadLine()会让您转到下一行。如果您将流的.Position存储在下方,则可以在以下.Position之后将其与ReadLine()进行比较。这是您刚刚阅读分隔符的字符串的长度。 分隔符的长度为currentPosition - previousPosition - line.Length

这样你就可以很容易地发现它是1还是2个字节(不知道细节,但你说你只关心这些位置)。

答案 2 :(得分:0)

File.ReadAllText将为您提供所有文件内容。对。所有。因此,在使用之前,最好先检查文件大小。

编辑:

全部阅读然后创建一个逐行产生的枚举器。

foreach(string line in Read("some.file"))
{ ... }


private IEnumerator Read(string file)
{
  string buffer = File.ReadAllText()
  for (int index=0;index<buffer.length;index++)
   {
      string line = ... logic to build a "line" here
      yield return line;
   }

   yield break;

}

答案 3 :(得分:0)

        FileStream fs = new FileStream("E:\\hh.txt", FileMode.Open, FileAccess.Read);
        BinaryReader read = new BinaryReader(fs);
        byte[] ch = read.ReadBytes((int)fs.Length);
        byte[] che=new byte[(int)fs.Length];
        int size = (int)fs.Length,j=0;
        for ( int i =0; i <= (size-1); i++)
        {
            if (ch[i] != '|')
            {
                che[j] = ch[i];
                j++;
            }

        }
        richTextBox1.Text = Encoding.ASCII.GetString(che);
        read.Close();
        fs.Close();