Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I can't remember where this came from exactly, but it has worked pretty well for me in the past.</p> <p>Replaced reader with writer:</p> <pre><code>/// &lt;summary&gt; /// A stream writer that allows its current position to be recorded and /// changed. This is not generally possible for stream writers, because /// of the use buffered reads. /// This writer can be used only for text content. Theoretically it can /// process any encoding, but was checked only for ANSI and UTF8 If you /// want to use this class with any other encoding, please check it. /// NOT SAFE FOR ASYNC WRITES. /// &lt;/summary&gt; public class PositionableStreamWriter : StreamWriter { /// &lt;summary&gt; /// Out best guess counted position. /// &lt;/summary&gt; private long _position; /// &lt;summary&gt; /// Guards against e.g. calling "Write(char[] buffer, int index, int count)" /// as part of the implementation of "Write(string value)", which would cause /// double counting. /// &lt;/summary&gt; private bool _guardRecursion; public PositionableStreamWriter(string fileName, bool append, Encoding enc) : base(fileName, append, enc) { CommonConstruct(); } public PositionableStreamWriter(Stream stream, Encoding enc) : base(stream, enc) { CommonConstruct(); } /// &lt;summary&gt; /// Encoding can really haven't preamble /// &lt;/summary&gt; private bool CheckPreamble(long lengthBeforeFlush) { byte[] preamble = this.Encoding.GetPreamble(); if (this.BaseStream.Length &gt;= preamble.Length) { if (lengthBeforeFlush == 0) return true; else // we would love to read, but base stream is write-only. return true; // just assume a preamble is there. } return false; } /// &lt;summary&gt; /// Use this property to get and set real position in file. /// Position in BaseStream can be not right. /// &lt;/summary&gt; public long Position { get { return _position; } set { this.Flush(); ((Stream)base.BaseStream).Seek(value, SeekOrigin.Begin); _position = value; } } public override void Write(char[] buffer) { if (buffer != null &amp;&amp; !_guardRecursion) _position += Encoding.GetByteCount(buffer); CallBase(() =&gt; base.Write(buffer)); } public override void Write(char[] buffer, int index, int count) { if (buffer != null &amp;&amp; !_guardRecursion) _position += Encoding.GetByteCount(buffer, index, count); CallBase(() =&gt; base.Write(buffer, index, count)); } public override void Write(string value) { if (value != null &amp;&amp; !_guardRecursion) _position += Encoding.GetByteCount(value); CallBase(() =&gt; base.Write(value)); } public override void WriteLine() { if (!_guardRecursion) _position += Encoding.GetByteCount(NewLine); CallBase(() =&gt; base.WriteLine()); } public override void WriteLine(char[] buffer) { if (buffer != null &amp;&amp; !_guardRecursion) _position += Encoding.GetByteCount(buffer) + Encoding.GetByteCount(NewLine); CallBase(() =&gt; base.WriteLine(buffer)); } public override void WriteLine(char[] buffer, int index, int count) { if (buffer != null &amp;&amp; !_guardRecursion) _position += Encoding.GetByteCount(buffer, index, count) + Encoding.GetByteCount(NewLine); CallBase(() =&gt; base.WriteLine(buffer, index, count)); } public override void WriteLine(string value) { if (value != null &amp;&amp; !_guardRecursion) _position += Encoding.GetByteCount(value) + Encoding.GetByteCount(NewLine); CallBase(() =&gt; base.WriteLine(value)); } private void CallBase(Action callBase) { if (_guardRecursion == true) callBase(); else { try { _guardRecursion = true; callBase(); } finally { _guardRecursion = false; } } } private void CommonConstruct() { var lenghtAtConstruction = BaseStream.Length; if (lenghtAtConstruction == 0) Flush(); // this should force writing the preamble if a preamble is being written. //we need to add length of symbol which is in begin of file and describes encoding of file if (CheckPreamble(lenghtAtConstruction)) { _position = this.Encoding.GetPreamble().Length; } } } </code></pre> <p>Usage:</p> <pre><code>class Program { static void Main(string[] args) { var pos = new List&lt;long&gt;(); using (var writer = new PositionableStreamWriter("tst.txt", false, Encoding.Unicode)) { pos.Add(writer.Position); writer.Write("abcde"); pos.Add(writer.Position); writer.WriteLine("Nope"); pos.Add(writer.Position); writer.WriteLine("Something"); pos.Add(writer.Position); writer.WriteLine("Another thing"); pos.Add(writer.Position); } using (var stream = File.Open("tst.txt", FileMode.Open)) using (var reader = new BinaryReader(stream)) { for (int i = 0; i &lt; pos.Count - 1; i++) { stream.Position = pos[i]; var len = (int)(pos[i + 1] - pos[i]); var buf = reader.ReadBytes(len); Console.Write(Encoding.Unicode.GetString(buf)); } } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload