C#StreamReader,“ReadLine”用于自定义分隔符

获得StreamReader.ReadLine()方法function的最佳方法是什么,但使用自定义(字符串)分隔符?

我想做的事情如下:

 String text; while((text = myStreamReader.ReadUntil("my_delim")) != null) { Console.WriteLine(text); } 

我试图使用Peek()StringBuilder来创建自己的,但效率太低。 我正在寻找建议或可能是一个开源解决方案。

谢谢。

编辑

我应该早点澄清一下……我已经看到了这个答案 ,但是,我不想将整个文件读入内存。

我想我会发布自己的解决方案。 它似乎工作得很好,代码相对简单。 随意评论。

 public static String ReadUntil(this StreamReader sr, String delim) { StringBuilder sb = new StringBuilder(); bool found = false; while (!found && !sr.EndOfStream) { for (int i = 0; i < delim.Length; i++) { Char c = (char)sr.Read(); sb.Append(c); if (c != delim[i]) break; if (i == delim.Length - 1) { sb.Remove(sb.Length - delim.Length, delim.Length); found = true; } } } return sb.ToString(); } 

此代码应适用于任何字符串分隔符。

 public static IEnumerable ReadChunks(this TextReader reader, string chunkSep) { var sb = new StringBuilder(); var sepbuffer = new Queue(chunkSep.Length); var sepArray = chunkSep.ToCharArray(); while (reader.Peek() >= 0) { var nextChar = (char)reader.Read(); if (nextChar == chunkSep[sepbuffer.Count]) { sepbuffer.Enqueue(nextChar); if (sepbuffer.Count == chunkSep.Length) { yield return sb.ToString(); sb.Length = 0; sepbuffer.Clear(); } } else { sepbuffer.Enqueue(nextChar); while (sepbuffer.Count > 0) { sb.Append(sepbuffer.Dequeue()); if (sepbuffer.SequenceEqual(chunkSep.Take(sepbuffer.Count))) break; } } } yield return sb.ToString() + new string(sepbuffer.ToArray()); } 

免责声明:

我对此进行了一些测试并且实际上比ReadLine方法慢,但我怀疑它是由于ReadLine方法中的enqueue / dequeue / sequenceEqual调用可以避免(因为分隔符总是\r\n )。

再次,我做了一些测试,它应该工作,但不要把它当作完美的,并随时纠正它。 ;)

这是我在需要的地方使用的一个简单的解析器(通常如果流式传输不是最重要的只读,而.Split完成工作),不是太优化但应该工作正常:
(它更像是一种类似斯普利特的方法 – 以及下面的更多注释)

  public static IEnumerable Split(this Stream stream, string delimiter, StringSplitOptions options) { var buffer = new char[_bufffer_len]; StringBuilder output = new StringBuilder(); int read; using (var reader = new StreamReader(stream)) { do { read = reader.ReadBlock(buffer, 0, buffer.Length); output.Append(buffer, 0, read); var text = output.ToString(); int id = 0, total = 0; while ((id = text.IndexOf(delimiter, id)) >= 0) { var line = text.Substring(total, id - total); id += delimiter.Length; if (options != StringSplitOptions.RemoveEmptyEntries || line != string.Empty) yield return line; total = id; } output.Remove(0, total); } while (read == buffer.Length); } if (options != StringSplitOptions.RemoveEmptyEntries || output.Length > 0) yield return output.ToString(); } 

…如果需要,你可以简单地切换到char分隔符

 while ((id = text.IndexOf(delimiter, id)) >= 0) 

…用

 while ((id = text.IndexOfAny(delimiters, id)) >= 0) 

(和id++而不是id+=和签名this Stream stream, StringSplitOptions options, params char[] delimiters

…也删除空等
希望能帮助到你

  public static String ReadUntil(this StreamReader streamReader, String delimiter) { StringBuilder stringBuilder = new StringBuilder(); while (!streamReader.EndOfStream) { stringBuilder.Append(value: (Char) streamReader.Read()); if (stringBuilder.ToString().EndsWith(value: delimiter)) { stringBuilder.Remove(stringBuilder.Length - delimiter.Length, delimiter.Length); break; } } return stringBuilder.ToString(); }