Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.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# C“StreamReader”;ReadLine";用于自定义分隔符_C#_Parsing_File Io_Streamreader_Delimiter - Fatal编程技术网

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

C# C“StreamReader”;ReadLine";用于自定义分隔符,c#,parsing,file-io,streamreader,delimiter,C#,Parsing,File Io,Streamreader,Delimiter,拥有StreamReader.ReadLine()方法的功能但使用自定义(字符串)分隔符的最佳方式是什么 我想做一些类似的事情: String text; while((text = myStreamReader.ReadUntil("my_delim")) != null) { Console.WriteLine(text); } 我尝试使用Peek()和StringBuilder制作自己的,但效率太低。我正在寻找建议或可能的开源解决方案 谢谢 编辑 我应该早一点澄清这一点……但是,我

拥有
StreamReader.ReadLine()
方法的功能但使用自定义(字符串)分隔符的最佳方式是什么

我想做一些类似的事情:

String text;
while((text = myStreamReader.ReadUntil("my_delim")) != null)
{
   Console.WriteLine(text);
}
我尝试使用
Peek()
StringBuilder
制作自己的,但效率太低。我正在寻找建议或可能的开源解决方案

谢谢

编辑


我应该早一点澄清这一点……但是,我不希望将整个文件读入内存。

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

public static IEnumerable<string> ReadChunks(this TextReader reader, string chunkSep)
{
    var sb = new StringBuilder();

    var sepbuffer = new Queue<char>(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());
}
公共静态IEnumerable ReadChunks(此文本阅读器,字符串chunkSep)
{
var sb=新的StringBuilder();
var sepbuffer=新队列(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)
{
让某人返回字符串();
sb.长度=0;
sepbuffer.Clear();
}
}
其他的
{
sepbuffer.Enqueue(nextChar);
而(sepbuffer.Count>0)
{
sb.Append(sepbuffer.Dequeue());
if(sepbuffer.SequenceEqual(chunkSep.Take(sepbuffer.Count)))
打破
}
}
}
yield返回sb.ToString()+新字符串(sepbuffer.ToArray());
}
免责声明:

我对此做了一些测试,实际上比
ReadLine
方法慢,但我怀疑这是因为
ReadLine
方法中的enqueue/dequeue/sequenceEqual调用可以避免的(因为分隔符总是
\r\n


同样,我做了一些测试,它应该可以工作,但不要认为它是完美的,请随意更正它

我在需要的地方使用了一个简单的解析器(通常,如果流式处理不是最重要的,只需读取和.Split即可),虽然没有太多优化,但应该可以正常工作:
(这更像是一种类似拆分的方法——下面还有更多注释)

…与

while ((id = text.IndexOfAny(delimiters, id)) >= 0)
(和
id++
而不是
id++=
和签名
此流、StringSplitOptions选项、参数char[]分隔符

…还删除空的等。

希望能有所帮助

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

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();
}
公共静态字符串ReadUntil(此StreamReader sr,字符串delim)
{
StringBuilder sb=新的StringBuilder();
bool-found=false;
而(!found&!sr.EndOfStream)
{
for(int i=0;i
为什么不使用ReadLine(),然后在字符串中搜索分隔符?通过使用
Peek()
StringBuilder
您基本上复制了
ReadLine()
StreamReader
中所做的事情。。。所以,对我来说,这么慢似乎很奇怪;你能发布你尝试过的吗?效率低下?效率有多低?性能是否明显不足?Duplicate:@AdamKing-不是Duplicate-OP特别需要一个字符串分隔符,而不是字符分隔符。如果在“found=true”后面加上一个“break”,则(对我来说)会更清楚一些。需要较少的心理处理。此解决方案仅在某些情况下有效。例如,如果分隔符为“xy”,则此算法将丢失“axxyb”中的分隔符,并将一直读取到流结束。
while ((id = text.IndexOfAny(delimiters, id)) >= 0)
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 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();
    }