5

Possible Duplicate:
How to read a text file reversely with iterator in C#

I am wondering if there is a way to read a text file from bottom to top without any performance penalty, the readLine, movenext approach, but reversed, is this sort of thing possible in .net?

To make matters more interesting the text file has around 100 000 lines in it, so I can't cheat with a readall, reverse...

Some more detail: I have a collection of incoming string values that is prefixed with an int ID that can be sorted. Unfortunately I get these IDs in the wrong order. The main issue is the sheer volume of the string values, and no RDBMS in the solution. So I really need a way to store the string values and then reverse the order of the storing during the processing. Text file came to mind because I don't have a better solution at this point in time.

Thanks in advance.

Community
  • 1
  • 1
JL.
  • 78,954
  • 126
  • 311
  • 459
  • There must be some type of low overhead "peek" method. – Kris Krause Feb 10 '10 at 23:05
  • 3
    don't you mean bottom to top? – Dave Archer Feb 10 '10 at 23:06
  • 1
    Yeah, top to bottom is kind of the standard way... – Dan Tao Feb 10 '10 at 23:07
  • 5
    Much as I'd love to get more rep for the work I put into implementing this, it really is a dupe: http://stackoverflow.com/questions/452902/how-to-read-a-text-file-reversely-with-iterator-in-c – Jon Skeet Feb 10 '10 at 23:10
  • Thanks Jon, I saw your answer, do you think it might be worthwhile for me to add lines normally then use an ODBC text driver to get the results in the reversed order? – JL. Feb 10 '10 at 23:16
  • @JL: Using the ODBC text driver may well be more expensive than just reading all the lines and reversing them in memory. How long is each line? 100,000 lines of 80 characters is still only about 16MB... – Jon Skeet Feb 10 '10 at 23:24
  • Since this question was closed... Why don't you use _two_ files? One which stores the strings and the other which stores the ID and the offset of the corresponding strings in the first file. –  Feb 10 '10 at 23:50

6 Answers6

1

Why not use the ReadToEnd() method of a StreamReader class, then work backwards... Admittedly it is not pretty but it works, I used a byte array to create a MemoryStream instance and the use that for the StreamReader instance, using pointer hocus-pocus, the data is read in a backward fashion.

unsafe
{
    byte[] b = System.Text.ASCIIEncoding.ASCII.GetBytes("Hello World! Foo wuz ere and so wuz bar");
    using (MemoryStream mStream = new MemoryStream(b))
    {
        string readStr;
        using (StreamReader sr = new StreamReader(mStream))
        {
            readStr = sr.ReadToEnd();
        }
        Console.WriteLine(readStr);
        fixed (char* beg = readStr)
        {
            char* p = beg + readStr.Length;
            while (p-- != beg)
            {
                Console.Write(*p);
            }
        }
    }
}
t0mm13b
  • 34,087
  • 8
  • 78
  • 110
0

Well, if you're willing to dive deep you could presumably use a binary reader and do your own reading...

You'd have to figure out the line endings in reverse, and figure out how to make sure you have the right encoding.

Pretty daunting I'd say.

John Weldon
  • 39,849
  • 11
  • 94
  • 127
0

Just a general answer. If there's some sort of peek() method, you could probably set your file pointer to filesize (or filesize - 1?) and then decrement the pointer until you reach 0. There is may be some class in .NET that abstracts this out. Of course, you have to define some sort of buffer size (basically define the size of the "chunks" of the file you are reading in). In that case, the filesize - 1 above might become filesize - bufferSize, and you would be incrementing your file pointer by bufferSize also.

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
0

I think you can do this can use the PInvoke to do this via the WINAPI. You need to create a memory mapped file, but only map the end of the file and then go upwards.

Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
0

So you get the values in the wrong order but want to retrive them in the correct order. Maybe a

Stack<T> 

Would work for you.

http://msdn.microsoft.com/en-us/library/3278tedw.aspx

Represents a variable size last-in-first-out (LIFO) collection of instances of the same arbitrary type.

Cory Charlton
  • 8,868
  • 4
  • 48
  • 68
  • Thanks, thats great knowledge but unfortunately I originally populate my list using a series of batch calls, otherwise that would work great. – JL. Feb 10 '10 at 23:20
-1

The ReadBlock method of the StreamReader class lets you read from a specific position. Not sure about the performance, you might want to just read it into an array, then reverse it.

Avindra Goolcharan
  • 4,032
  • 3
  • 41
  • 39
  • Would do, except I am beyond the point of loading it all into a collection due to memory constraints and high volumes, unfortunately. – JL. Feb 10 '10 at 23:09
  • ReadBlock lets you read *into* a specific position in the array it's writing to. It doesn't let you specify the index to read *from* within the reader. – Jon Skeet Feb 10 '10 at 23:12