Reading a file backwards in C#

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Neil Patel

    #1

    Reading a file backwards in C#

    I have a log file that puts the most recent record at the bottom of the file. Each line is delimited by a \r\n

    Does anyone know how to seek to the end of the file and start reading backwards?
  • Rick Sawtell

    #2
    Re: Reading a file backwards in C#

    Not sure about that, but you could always read the file into an array
    row-by-row and then use a loop to read it backwards.


    Rick Sawtell
    MCT, MCSD, MCDBA



    "Neil Patel" <Neil Patel@discussio ns.microsoft.co m> wrote in message
    news:EA59FF94-7E38-4E33-B6F9-A1E170B18E6A@mi crosoft.com...[color=blue]
    > I have a log file that puts the most recent record at the bottom of the[/color]
    file. Each line is delimited by a \r\n[color=blue]
    >
    > Does anyone know how to seek to the end of the file and start reading[/color]
    backwards?


    Comment

    • Shakir Hussain

      #3
      Re: Reading a file backwards in C#

      Couple of ways to do that.

      Method 1:

      //initialize streamreader
      StreamReader myStream= new StreamReader(@" c:\myfile.txt") ;
      //seek file pointer to end
      myStream.BaseSt ream.Seek(1024, SeekOrigin.End) ;

      //intialize array of size 1024
      char [] arr = new char[1024];
      //loop now and read backwards
      While(myStream. BaseStream.Posi tion > 0)
      {
      arr.Initialize( );
      //Move back 1024 bytes (for better control)
      myStream.BaseSt ream.Seek(1024, SeekOrigin.Curr ent);
      //read 1024 bytes.
      int bytesRead = myStream.Read(a rr,0,1024);

      }

      Method:2

      //initialize streamreader
      StreamReader myStream = new StreamReader(@" c:\myfile.txt") ;
      //read all the contents and store in string
      string WholeFileString =myStream.ReadT oEnd();
      //convert to array
      char []strArray = WholeFileString .ToCharArray();
      //reverse the array
      Array.Reverse(s trArray);
      //again convert to string
      string newStr = new string(strArray );
      //specify the split array (Note \r\n must be specified reverse becoz
      string is reverse
      char [] split = new char[2];
      split[0] = '\n';
      split[1] = '\r';
      //receive the string array after spliting
      string [] Lines = newStr.Split(sp lit);

      lines[0] = ; //last line of the file
      lines[lines.Length-1] = ; //first line of the file

      --
      Shak
      (Houston)


      "Neil Patel" <Neil Patel@discussio ns.microsoft.co m> wrote in message
      news:EA59FF94-7E38-4E33-B6F9-A1E170B18E6A@mi crosoft.com...[color=blue]
      > I have a log file that puts the most recent record at the bottom of the[/color]
      file. Each line is delimited by a \r\n[color=blue]
      >
      > Does anyone know how to seek to the end of the file and start reading[/color]
      backwards?


      Comment

      • Shakir Hussain

        #4
        Re: Reading a file backwards in C#

        Sorry some typos
        [color=blue]
        > myStream.BaseSt ream.Seek(1024, SeekOrigin.End) ;[/color]

        this must be

        myStream.BaseSt ream.Seek(0,See kOrigin.End);
        [color=blue]
        > myStream.BaseSt ream.Seek(1024, SeekOrigin.Curr ent);[/color]

        this must be
        [color=blue]
        > myStream.BaseSt ream.Seek(-1024,SeekOrigin .Current);[/color]


        --
        Shak
        (Houston)



        "Shakir Hussain" <shak@fakedomai n.com> wrote in message
        news:eBREq15aEH A.3480@TK2MSFTN GP11.phx.gbl...[color=blue]
        > Couple of ways to do that.
        >
        > Method 1:
        >
        > //initialize streamreader
        > StreamReader myStream= new StreamReader(@" c:\myfile.txt") ;
        > //seek file pointer to end
        > myStream.BaseSt ream.Seek(1024, SeekOrigin.End) ;
        >
        > //intialize array of size 1024
        > char [] arr = new char[1024];
        > //loop now and read backwards
        > While(myStream. BaseStream.Posi tion > 0)
        > {
        > arr.Initialize( );
        > //Move back 1024 bytes (for better control)
        > myStream.BaseSt ream.Seek(1024, SeekOrigin.Curr ent);
        > //read 1024 bytes.
        > int bytesRead = myStream.Read(a rr,0,1024);
        >
        > }
        >
        > Method:2
        >
        > //initialize streamreader
        > StreamReader myStream = new StreamReader(@" c:\myfile.txt") ;
        > //read all the contents and store in string
        > string WholeFileString =myStream.ReadT oEnd();
        > //convert to array
        > char []strArray = WholeFileString .ToCharArray();
        > //reverse the array
        > Array.Reverse(s trArray);
        > //again convert to string
        > string newStr = new string(strArray );
        > //specify the split array (Note \r\n must be specified reverse becoz
        > string is reverse
        > char [] split = new char[2];
        > split[0] = '\n';
        > split[1] = '\r';
        > //receive the string array after spliting
        > string [] Lines = newStr.Split(sp lit);
        >
        > lines[0] = ; //last line of the file
        > lines[lines.Length-1] = ; //first line of the file
        >
        > --
        > Shak
        > (Houston)
        >
        >
        > "Neil Patel" <Neil Patel@discussio ns.microsoft.co m> wrote in message
        > news:EA59FF94-7E38-4E33-B6F9-A1E170B18E6A@mi crosoft.com...[color=green]
        > > I have a log file that puts the most recent record at the bottom of the[/color]
        > file. Each line is delimited by a \r\n[color=green]
        > >
        > > Does anyone know how to seek to the end of the file and start reading[/color]
        > backwards?
        >
        >[/color]


        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: Reading a file backwards in C#

          Shakir Hussain <shak@fakedomai n.com> wrote:[color=blue]
          > Couple of ways to do that.
          >
          > Method 1:
          >
          > //initialize streamreader
          > StreamReader myStream= new StreamReader(@" c:\myfile.txt") ;
          > //seek file pointer to end
          > myStream.BaseSt ream.Seek(1024, SeekOrigin.End) ;
          >
          > //intialize array of size 1024
          > char [] arr = new char[1024];
          > //loop now and read backwards
          > While(myStream. BaseStream.Posi tion > 0)
          > {
          > arr.Initialize( );
          > //Move back 1024 bytes (for better control)
          > myStream.BaseSt ream.Seek(1024, SeekOrigin.Curr ent);
          > //read 1024 bytes.
          > int bytesRead = myStream.Read(a rr,0,1024);
          >
          > }[/color]

          Note that you've got a bit of confusion here between bytes and
          characters - a StreamReader returns the number of *characters* read,
          not bytes... and that introduces another problem. There's nothing to
          say that moving backwards 1024 bytes will even put you at the start of
          a character - it could be in the middle of a multi-byte character.

          You also need to discard the StreamReader's buffer after repositioning.

          Also, the first parameter to Seek should be -1024, not 1024, otherwise
          it's moving forwards not backwards.

          Finally, moving back 1024 bytes doesn't mean you'll move back 1024
          characters, so the code above could mean reading some characters twice.
          [color=blue]
          > Method:2
          >
          > //initialize streamreader
          > StreamReader myStream = new StreamReader(@" c:\myfile.txt") ;
          > //read all the contents and store in string
          > string WholeFileString =myStream.ReadT oEnd();
          > //convert to array
          > char []strArray = WholeFileString .ToCharArray();
          > //reverse the array
          > Array.Reverse(s trArray);
          > //again convert to string
          > string newStr = new string(strArray );
          > //specify the split array (Note \r\n must be specified reverse becoz
          > string is reverse
          > char [] split = new char[2];
          > split[0] = '\n';
          > split[1] = '\r';
          > //receive the string array after spliting
          > string [] Lines = newStr.Split(sp lit);
          >
          > lines[0] = ; //last line of the file
          > lines[lines.Length-1] = ; //first line of the file[/color]

          That gives every line of the file reversed as well, which probably
          isn't desired. I'd suggest:

          ArrayList list = new ArrayList();
          using (StreamReader reader = new StreamReader(@" c:\myfile.txt")
          {
          string line;
          while ( (line=reader.Re adLine()) != null)
          {
          list.Add(line);
          }
          }
          list.Reverse();

          That gives you an ArrayList of each line of the file, starting from the
          end. It probably doesn't help the OP, however, as I'd assume that the
          idea is to avoid having to read the whole file.

          --
          Jon Skeet - <skeet@pobox.co m>
          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

          If replying to the group, please do not mail me too

          Comment

          • Jon Skeet [C# MVP]

            #6
            Re: Reading a file backwards in C#

            <"=?Utf-8?B?TmVpbCBQYXR lbA==?=" <Neil
            Patel@discussio ns.microsoft.co m>> wrote:[color=blue]
            > I have a log file that puts the most recent record at the bottom of
            > the file. Each line is delimited by a \r\n
            >
            > Does anyone know how to seek to the end of the file and start reading
            > backwards?[/color]

            It would be possible to have a type of stream which wrapped another
            stream (a seekable one) and read it backwards. It would buffer a chunk
            at a time, and offer up the contents of that buffer backwards. It
            wouldn't be particularly hard to write, so long as you kept everything
            nice and simple.

            What's much harder is writing an Encoding which is capable of taking
            that backwards stream and converting it into a backwards sequence of
            characters. In some encodings it may even be impossible. For any
            encoding with a fixed size, it's pretty easy. (In fact, it would be
            possible to write an encoding which, given another encoding and the
            fixed number of bytes per character used by that encoding, created a
            backwards encoding for it.)

            For UTF-8 it's possible, as you can detect when a character ends.
            (Either the top two bits are set or the top bit is unset.) It's non-
            trivial to write though.

            The main point is you'd need to do this for each encoding you're
            interested in - which encoding is the log file in? I could probably be
            persuaded to help out with the backwards stream and a single encoding,
            but I'm not going to start writing multiple encodings on the off-chance
            that I write the one that's useful to you :)

            --
            Jon Skeet - <skeet@pobox.co m>
            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

            If replying to the group, please do not mail me too

            Comment

            • guy

              #7
              Re: Reading a file backwards in C#

              or push each row onto a stack, then you pop them off...

              hth guy

              (assuming you have enough ram to read the whole file)

              "Rick Sawtell" wrote:
              [color=blue]
              > Not sure about that, but you could always read the file into an array
              > row-by-row and then use a loop to read it backwards.
              >
              >
              > Rick Sawtell
              > MCT, MCSD, MCDBA
              >
              >
              >
              > "Neil Patel" <Neil Patel@discussio ns.microsoft.co m> wrote in message
              > news:EA59FF94-7E38-4E33-B6F9-A1E170B18E6A@mi crosoft.com...[color=green]
              > > I have a log file that puts the most recent record at the bottom of the[/color]
              > file. Each line is delimited by a \r\n[color=green]
              > >
              > > Does anyone know how to seek to the end of the file and start reading[/color]
              > backwards?
              >
              >
              >[/color]

              Comment

              Working...