views:

712

answers:

9

This is the way I read file:

    public static string readFile(string path)
    {
        StringBuilder stringFromFile = new StringBuilder();
        StreamReader SR;
        string S;
        SR = File.OpenText(path);
        S = SR.ReadLine();
        while (S != null)
        {
            stringFromFile.Append(SR.ReadLine());
        }
        SR.Close();
        return stringFromFile.ToString();
    }

The problem is it so long (the .txt file is about 2.5 megs). Took over 5 minutes. Is there a better way?

Solution taken

    public static string readFile(string path)
    {

       return File.ReadAllText(path);

    }

Took less than 1 second... :)

+5  A: 

Leaving aside the horrible variable names and the lack of a using statement (you won't close the file if there are any exceptions) that should be okay, and certainly shouldn't take 5 minutes to read 2.5 megs.

Where does the file live? Is it on a flaky network share?

By the way, the only difference between what you're doing and using File.ReadAllText is that you're losing line breaks. Is this deliberate? How long does ReadAllText take?

Jon Skeet
Off topic, but Jon, I enjoyed your appearance on Dot Net Rocks.
Giovanni Galbo
@Giovanni: Great - it was a lot of fun, if somewhat nerve-wracking.
Jon Skeet
You missed the infinite loop that Marcus pointed out.
Kevin
A: 

Do you need the entire 2.5 Mb in memory at once?

If not, I would try to work with what you need.

Greg Dean
This is good advice. I had a colleague who seemed to think he needed an entire 300+MB XML file in memory at once. Didn't work too well.
Greg D
+1  A: 

Use System.IO.File.RealAllLines instead.

http://msdn.microsoft.com/en-us/library/system.io.file.readalllines.aspx

Alternatively, estimating the character count and passing that to StringBuilder's constructor as the capacity should speed it up.

PlacidBox
+2  A: 
return System.IO.File.ReadAllText(path);
Ian Potter
+1  A: 

Try this, should be much faster:

var str = System.IO.File.ReadAllText(path);
return str.Replace(Environment.NewLine, "");
Konrad Rudolph
Faster than System.IO.File.ReadAllText(path);?
Daok
@Daok: You're right. My point was the use of `Replace`. I overlooked the easier solution.
Konrad Rudolph
A: 

The loop and StringBuilder may be redundant; Try using ReadToEnd.

gimel
+4  A: 
S = SR.ReadLine();
while (S != null)
{
    stringFromFile.Append(SR.ReadLine());
}

Of note here, S is never set after that initial ReadLine(), so the S != null condition never triggers if you enter the while loop. Try:

S = SR.ReadLine();
while (S != null)
{
    stringFromFile.Append(S = SR.ReadLine());
}

or use one of the other comments.

If you need to remove newlines, use string.Replace(Environment.NewLine, "")

Marcus Griep
Good catch on the infinite loop. Up vote for you
Kevin
You are right +1 too. Thx, this is the reason it took so long. I took some code on the web and try to clean it up. My mistake!
Daok
actually, wouldn't this miss the first line of the file?
Kevin
Also a good point, Kevin. This is also true.
Marcus Griep
+2  A: 

Marcus Griep has it right. IT's taking so long because YOU HAVE AN INFINITE LOOP. copied your code and made his changes and it read a 2.4 M text file in less than a second.

but I think you might miss the first line of the file. Try this.


S = SR.ReadLine();
while (S != null){
    stringFromFile.Append(S);
    S = SR.ReadLine();
}

Kevin
A: 

By the way: Next time you're in a similar situation, try pre-allocating memory. This improves runtime drastically, regardless of the exact data structures you use. Most containers (StringBuilder as well) have a constructor that allow you to reserve memory. This way, less time-consuming reallocations are necessary during the read process.

For example, you could write the following if you want to read data from a file into a StringBuilder:

var info = new FileInfo(path);
var sb = new StringBuilder((int)info.Length);

(Cast necessary because System.IO.FileInfo.Length is long.)

Konrad Rudolph