4

I have the following code:

StringReader contentReader = new StringReader(this.dataContent.ToString());

After I parse my DataContent, I need to reset the poistion of the contentReader to begining of the string. How do I do it? I dont see a set poistion option in StringReader

Sam Axe
  • 33,313
  • 9
  • 55
  • 89
savi
  • 497
  • 2
  • 12
  • 27

5 Answers5

9

Set it to a new instance of StringReader. I don't believe you can change the position of an existing one.

contentReader = new StringReader(this.dataContent.ToString());

MatthewHagemann
  • 1,167
  • 2
  • 9
  • 20
4

Another option would be to load the string into a MemoryStream then use a StreamReader to iterate over it. MemoryStream definitely supports position resets on a memory stream.

String data = "Hello! My name it Inigo Montoya.";
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
{
    using (StreamReader reader = new StreamReader(stream))
    {
        // Do your parsing here using the standard StreamReader methods.
        // They should be fairly comparable to StringReader.

        // When all done, reset stream position to the beginning.
        stream.Seek(0, SeekOrigin.Begin);
    }
}
Sam Axe
  • 33,313
  • 9
  • 55
  • 89
  • You **must** call `reader.DiscardBufferedData()` after setting the stream position. https://msdn.microsoft.com/en-us/library/system.io.streamreader.discardbuffereddata(v=vs.110).aspx – Steven Liekens Oct 11 '15 at 08:01
  • @StevenLiekens: `reader.Flush()` is another option. However, both of these methods are only needed if the stream has been written to. In this instance neither call is needed. – Sam Axe Oct 13 '15 at 21:39
  • There is no `StreamReader.Flush()`. Only `DiscardBufferedData()`. Which you have to call after seeking, because the reader will read any buffered bytes before hitting the stream again if you don't. – Steven Liekens Oct 13 '15 at 21:47
3

The StringReader keeps track of its position within the string with a private int field called _pos, if you want to reset it you can use a simple extension method like this:

public static void Reset(this StringReader reader)
{
    reader.GetType()
          .GetField("_pos", BindingFlags.NonPublic | BindingFlags.Instance)
          .SetValue(reader, 0);
}

And a test method:

[Test]
public void Reset()
{
    const string random = "this is a test string";
    using(var reader = new StringReader(random))
    {
        Assert.AreEqual(random, reader.ReadToEnd());
        Assert.IsEmpty(reader.ReadToEnd());

        reader.Reset();
        Assert.AreEqual(random, reader.ReadToEnd());
        Assert.IsEmpty(reader.ReadToEnd());
    }
}
MrLore
  • 3,759
  • 2
  • 28
  • 36
0

You can use extension method for the StreamReader and handle it by yourself:

public static class SRExtentions
{
    public static void ResetToBeginning(this StringReader reader)
    {
        SetPrivateField(reader, "_pos", 0);
    }

    private static void SetPrivateField(this object obj, string name, object value)
    {
        BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
        Type type = obj.GetType();
        FieldInfo field = type.GetField(name, flags);
        field.SetValue(obj, value);
    }
}
Tiger Galo
  • 289
  • 4
  • 15
-1

See also a similar question : How do you reset a C# .NET TextReader cursor back to the start point?

But as Matthew said, the solution is probably to simply create a new one.

Community
  • 1
  • 1
Xavier Leclercq
  • 313
  • 2
  • 8