我有以下代码:
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);
}
这段代码有效,但SOOOOO SLOW因为我循环遍历buffer
数组中的每个字符并ToString()
。想象一下,当它摄取和复制一个823,000个字符的文件时,速度有多慢。
有没有办法将完全填充的buffer
转换为字符串并立即添加它而不是循环遍历数组中的每个字符?或者,一般来说,有没有更快的方法呢?
我为这段代码感到羞耻。
答案 0 :(得分:6)
实际上,这并不是为什么它如此缓慢。这很慢,因为你正在重复string concatenation and that's O(n^2)
。如果您使用StringBuilder
,您会看到更好的效果。你也可以只创建一个字符数组,并调用带有这样一个数组的constructor of string
。
但更好的是,一起跳过字符串,然后将缓冲区写到sw
。
答案 1 :(得分:1)
您应该将字符数组传递给string
构造函数:
string strFileContents = new string(buffer);
我希望它快得多。
答案 2 :(得分:1)
不要,你这么近......我想,你可以像这样编写输出: 你似乎把它循环了两次......
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);
}
}
答案 3 :(得分:1)
我可以问为什么你这样做。因为看起来你的目标是将一个文件的内容移动到另一个char-by-char而不进行其他处理。在这种情况下,有更好的方法。
但即使您确实需要阅读所有内容,请查看File.ReadAllLines
答案 4 :(得分:1)
只需使用带有缓冲区,偏移量和长度的重载,并完全跳过转换。
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 );
}
}
答案 5 :(得分:1)
不要使用String。改为使用Stringbuilder。
在.NET中,字符串是不可变的,这意味着每次更改字符串时,它都会生成一个副本。这会随着时间的推移而减慢。
答案 6 :(得分:1)
应该能够做一个GetString()。它一次读取2048个字节进行转换。您还可以指定编码类型来处理不同的字符集。
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);
}