Reputation: 2490
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
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
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
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
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
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
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
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