none
How to file position after reading one line from a file? RRS feed

  • Question

  • Hi,

    In C# how to read a line and after reading how to get the file position?

    How to achieve both?

     FileStream fStream = File.OpenRead(filePath);
     var reader = new StreamReader(fStream);
     while (!reader.EndOfStream)
     {
                        
     string line = reader.ReadLine();
                      
       }

    After reading a line if I call fStream.Position , it gives position value as entire file length only.

    Please help me to resolve my problem.



    • Edited by sgrm123 Thursday, May 16, 2019 2:51 PM
    Thursday, May 16, 2019 2:25 PM

All replies

  • You could better use the BaseStream property of your reader to get your current position. And because either FileStream as StreamReader apply IDisposable you should better enclose the whole in a using clause:
    using (StreamReader reader = new StreamReader(new FileStream(path, FileMode.Open)))
    {
    	while ((line = reader.ReadLine()) != null)
    	{
    	    Debug.WriteLine(reader.BaseStream.Position);
           	    //do sth. with line.
    	}
    }
    
    wizend
    • Edited by Wizend Thursday, May 16, 2019 2:43 PM
    • Marked as answer by sgrm123 Thursday, May 16, 2019 2:45 PM
    • Unmarked as answer by sgrm123 Thursday, May 16, 2019 2:47 PM
    Thursday, May 16, 2019 2:41 PM
  • You could better use the BaseStream property of your reader to get your current position. And because either FileStream as StreamReader apply IDisposable you should better enclose the whole in a using clause:
    using (StreamReader reader = new StreamReader(new FileStream(path, FileMode.Open)))
    {
    	while ((line = reader.ReadLine()) != null)
    	{
    	    Debug.WriteLine(reader.BaseStream.Position);
           	    //do sth. with line.
    	}
    }
    
    wizend
    reader.BaseStream.Position gives the whole length of file only. It is not giving current index(position).
    Thursday, May 16, 2019 2:49 PM
  • Yes, StreamReader is buffering the FileStream. So, when your program gets to that BaseStream.Position line StreamReader probably  will already have buffered the complete file.

    Maybe this discussion in a StackOverflow thread about how to get over this problem will help you.

    wizend

    Thursday, May 16, 2019 3:42 PM
  • Hi sgrm123,

    Based on your description, you want to know file position after reading one line from a file.

    I do a simple code, you could have a look.

     class Program
        {
            static void Main(string[] args)
            {
                FileStream fStream = File.OpenRead(@"D:\2.txt");
                var reader = new StreamReader(fStream);
                while (!reader.EndOfStream)
                {
    
                    string line = reader.ReadLine();
                    var index = reader.GetPosition();
                    Console.WriteLine(index);
    
                }
                Console.ReadKey();
            }
        }
    
        public static class StreamReaderExtensions
        {
            readonly static FieldInfo charPosField = typeof(StreamReader).GetField("charPos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.DeclaredOnly);
            readonly static FieldInfo byteLenField = typeof(StreamReader).GetField("byteLen", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.DeclaredOnly);
            readonly static FieldInfo charBufferField = typeof(StreamReader).GetField("charBuffer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.DeclaredOnly);
    
            public static long GetPosition(this StreamReader reader)
            {
                //shift position back from BaseStream.Position by the number of bytes read
                //into internal buffer.
                int byteLen = (int)byteLenField.GetValue(reader);
                var position = reader.BaseStream.Position - byteLen;
    
                //if we have consumed chars from the buffer we need to calculate how many
                //bytes they represent in the current encoding and add that to the position.
                int charPos = (int)charPosField.GetValue(reader);
                if (charPos > 0)
                {
                    var charBuffer = (char[])charBufferField.GetValue(reader);
                    var encoding = reader.CurrentEncoding;
                    var bytesConsumed = encoding.GetBytes(charBuffer, 0, charPos).Length;
                    position += bytesConsumed;
                }
    
                return position;
            }
    
           
        }

    Result:

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, May 17, 2019 5:20 AM
    Moderator

  • In C# how to read a line and after reading how to get the file position?

    How to achieve both?



    You should explain why you want the file position. What do you intend to do
    with that information?

    If you take the position *after* reading a line it will be the position 
    following the line, not the position of the line itself.

    There are various ways to do Seek operations on a file if that is your goal, 
    but it generally works best when doing "binary" reading rather than *text*
    reading. Seeking sometimes has issues with the way CRLF pairs are counted
    when reading in "text" modes.

    You can read a "text" file using a BinaryReader and detect newlines yourself.
    Positions after each line read should be available. For example:

    static void Main(string[] args)
    {
        string filePath = "../../testfile.txt";
    
        StringBuilder str = new StringBuilder("");
        char ch;
        using (BinaryReader breader = new BinaryReader(File.Open(filePath, 
            FileMode.Open, FileAccess.Read)))
        {
            Console.WriteLine(breader.BaseStream.Length);
            try
            {
                while (true)
                {
                    do
                    {
                        ch = breader.ReadChar();
                        str.Append(ch);
                    } while (ch != '\n');
    
                    Console.Write(str);
                    str.Clear();
                    Console.WriteLine(breader.BaseStream.Position);
                }
            }
            catch (EndOfStreamException)
            {
                if(str.ToString() != "")
                {
                    Console.WriteLine(str);
                    Console.WriteLine(breader.BaseStream.Position);
                }
            }
        }
    }
    

    - Wayne

    Friday, May 17, 2019 8:38 PM
  • Hi

    Is your problem solved? If so, please post "Mark as answer" to the appropriate answer, so that it will help other members to find the solution quickly if they face a similar issue.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, May 21, 2019 8:39 AM
    Moderator