Isaiah Nelson
Isaiah Nelson

Reputation: 2490

How to "ToString" Character Arrays of Large Quantities?

I have the following code:

public static void PrependEntitiesToFile(string pathToFile)
{
    char[] buffer = new char[10000];
    FileInfo file = new FileInfo(pathToFile);

    string renamedFile = file.FullName + ".orig";
    System.IO.File.Move(file.FullName, renamedFile);

    using (StreamReader sr = new StreamReader(renamedFile))
    using (StreamWriter sw = new StreamWriter(file.FullName, false))
    {
        string entityDeclaration = "foo";
        sw.Write(entityDeclaration);
        string strFileContents = string.Empty;
        int read;
        while ((read = sr.Read(buffer, 0, buffer.Length)) > 0)
        {
            for (int i = 0; i < buffer.Length; i++)
            {
                strFileContents += buffer[i].ToString();
            }
        }
        sw.Write(strFileContents, 0, strFileContents.Length);

    }

    System.IO.File.Delete(renamedFile);
}

This code works but its SOOOOO SLOW because I am looping through each character in the buffer array and ToString()-ing it. Imagine how slow it is when its ingesting and duplicating a 823,000 character file.

Is there a way to convert a fully populated buffer to a string and add it at once rather than looping through each character in the array? Or, generically speaking, is there just a faster way to this?

I am so ashamed of this code.

Upvotes: 0

Views: 158

Answers (7)

Brian
Brian

Reputation: 2229

Should be able to do a GetString(). It reads in 2048 bytes at a time to do the conversion. You can also specify an encoding type to handle different charsets.

public enum EncodingType 
{ 
    ASCII, 
    Unicode, 
    UTF7, 
    UTF8 
} 
public static string ByteArrayToString(byte[] bytes) 
{ 
    return ByteArrayToString(bytes, EncodingType.Unicode); 
} 

public static string ByteArrayToString(byte[] bytes, EncodingType encodingType) 
{ 
    System.Text.Encoding encoding=null; 
    switch (encodingType) 
    { 
    case EncodingType.ASCII: 
        encoding=new System.Text.ASCIIEncoding(); 
        break;    
    case EncodingType.Unicode: 
        encoding=new System.Text.UnicodeEncoding(); 
        break;    
    case EncodingType.UTF7: 
        encoding=new System.Text.UTF7Encoding(); 
        break;    
    case EncodingType.UTF8: 
        encoding=new System.Text.UTF8Encoding(); 
        break;    
    } 
    return encoding.GetString(bytes); 
} 

Upvotes: 1

pearcewg
pearcewg

Reputation: 9613

Don't use String. Use Stringbuilder instead.

In .NET, string are immutable, which means each time you change one, it makes a copy. That slows it down over time.

Upvotes: 1

tvanfosson
tvanfosson

Reputation: 532435

Just use the overload that takes a buffer, offset, and length and skip the conversion altogether.

using (StreamReader sr = new StreamReader(renamedFile))
using (StreamWriter sw = new StreamWriter(file.FullName, false))
{
    string entityDeclaration = "foo";
    sw.Write(entityDeclaration);
    string strFileContents = string.Empty;
    int read;
    while ((read = sr.Read(buffer, 0, buffer.Length)) > 0)
    {
        sw.Write( buffer, 0, read );
    }

}

Upvotes: 1

Eoin Campbell
Eoin Campbell

Reputation: 44268

Can I ask why you are doing this. BEcause it looks like your goal is to move the contents of one file to another char-by-char with no other processing. In which case there are much better ways.

But even if you do need to read everything in, have a look at File.ReadAllLines

Upvotes: 1

mindandmedia
mindandmedia

Reputation: 6825

don't be, you are so close... i think, you can write the output like this: you seem to be it looping it twice...

using (StreamReader sr = new StreamReader(renamedFile))
using (StreamWriter sw = new StreamWriter(file.FullName, false))
{
    string entityDeclaration = "foo";
    sw.Write(entityDeclaration);
    string strFileContents = string.Empty;
    int read;
    while ((read = sr.Read(buffer, 0, buffer.Length)) > 0)
    {
        sw.Write(buffer);
    }
}

Upvotes: 1

jason
jason

Reputation: 241583

Actually, that's not why it's so slow. It's slow because you're doing a repeated string concatenation and that's O(n^2). You'd see better performance if you used a StringBuilder. You could also just make an array of the characters, and call the constructor of string that takes such an array.

But even better, skip the string all together, and just write the buffer out to sw.

Upvotes: 6

recursive
recursive

Reputation: 86074

You should just pass your character array to the string constructor:

string strFileContents = new string(buffer);

I expect that to be much faster.

Upvotes: 1

Related Questions