lin*_*use 6 .net c# textwriter
我开始做以下事情:
using (TextWriter textWriter = new StreamWriter(filePath, append))
{
foreach (MyClassA myClassA in myClassAs)
{
textWriter.WriteLine(myIO.GetCharArray(myClassA));
if (myClassA.MyClassBs != null)
myClassA.MyClassBs.ToList()
.ForEach(myClassB =>
textWriter.WriteLine(myIO.GetCharArray((myClassB)));
if (myClassA.MyClassCs != null)
myClassA.MyClassCs.ToList()
.ForEach(myClassC =>
textWriter.WriteLine(myIO.GetCharArray(myClassC)));
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎很慢(35,000行约35秒).
然后我尝试按照这里的示例创建一个缓冲区,使用以下代码,但它没有获得任何东西.我仍然看到大约35秒的时间.我是如何实现缓冲区的?
using (TextWriter textWriter = new StreamWriter(filePath, append))
{
char[] newLineChars = Environment.NewLine.ToCharArray();
//Chunk through 10 lines at a time.
int bufferSize = 500 * (RECORD_SIZE + newLineChars.Count());
char[] buffer = new char[bufferSize];
int recordLineSize = RECORD_SIZE + newLineChars.Count();
int bufferIndex = 0;
foreach (MyClassA myClassA in myClassAs)
{
IEnumerable<IMyClass> myClasses =
new List<IMyClass> { myClassA }
.Union(myClassA.MyClassBs)
.Union(myClassA.MyClassCs);
foreach (IMyClass myClass in myClasses)
{
Array.Copy(myIO.GetCharArray(myClass).Concat(newLineChars).ToArray(),
0, buffer, bufferIndex, recordLineSize);
bufferIndex += recordLineSize;
if (bufferIndex >= bufferSize)
{
textWriter.Write(buffer);
bufferIndex = 0;
}
}
}
if (bufferIndex > 0)
textWriter.Write(buffer);
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来实现这一目标?
我强烈怀疑你的大部分时间都没花在I/O上.除非那些线路真的很长,否则它不可能需要35秒才能写入35,000行.
最有可能的是GetCharArray,无论如何,大部分时间都花在了方法上.
一些建议:
如果您确实认为I/O是问题,请增加流的缓冲区大小.调用StreamWriter构造函数,该构造函数允许您指定缓冲区大小.例如,
using (TextWriter textWriter = new StreamWriter(filePath, append, Encoding.Utf8, 65536))
Run Code Online (Sandbox Code Playgroud)
这将比默认的4K缓冲区大小更好.缓冲区大小高于64K通常不常用,实际上可能会降低性能.
不要预先缓冲行或附加到StringBuilder.这可能会使您的性能提升很小,但复杂性成本却很高.小的性能提升不值得维护噩梦.
利用foreach.你有这个代码:
if (myClassA.MyClassBs != null)
myClassA.MyClassBs.ToList()
.ForEach(myClassB =>
textWriter.WriteLine(myIO.GetCharArray((myClassB)));
Run Code Online (Sandbox Code Playgroud)
这必须从任何MyClassBs集合创建一个具体的列表,然后枚举它.为什么不直接枚举这个东西:
if (myClassA.MyClassBs != null)
{
foreach (var myClassB in myClassA.MyClassBs)
{
textWriter.WriteLine(myIO.GetCharArray((myClassB)));
}
}
Run Code Online (Sandbox Code Playgroud)
这将节省您ToList在创建列表时枚举集合所需的内存和时间.
所有这一切,几乎可以肯定你的GetCharArray方法是一直在采取的方法.如果你真的想加快你的计划,那就看看吧.试图优化写作StreamWriter是浪费时间.你不会在那里获得显着的性能提升.
我整理了一个我认为更清晰的简单片段;但是,话又说回来,我不太确定你想要实现什么目标。另外,我没有你们的任何课程,所以我无法真正进行任何类型的测试。
该示例的作用与您的基本相同;只是它使用了一些通用方法,并且所有的编写都在一个地方完成。
string filePath = "MickeyMouse.txt";
bool append = false;
List<MyClassA> myClassAs = new List<MyClassA> { new MyClassA() };
List<char[]> outputLines = new List<char[]>();
foreach (MyClassA myClassA in myClassAs)
{
outputLines.Add(myIO.GetCharArray(myClassA));
if (myClassA.MyClassBs != null)
outputLines.AddRange(myClassA.MyClassBs.Select(myClassB => myIO.GetCharArray(myClassB)));
if (myClassA.MyClassCs != null)
outputLines.AddRange(myClassA.MyClassCs.Select(myClassC => myIO.GetCharArray(myClassC)));
}
var lines = outputLines.Select(line => string.Concat<char>(line));
if (append)
File.AppendAllLines(filePath, lines);
else
File.WriteAllLines(filePath, lines);
Run Code Online (Sandbox Code Playgroud)
这是 StringBuilder 版本:
string filePath = "MickeyMouse.txt";
bool append = false;
List<MyClassA> myClassAs = new List<MyClassA> { new MyClassA() };
StringBuilder outputLines = new StringBuilder();
foreach (MyClassA myClassA in myClassAs)
{
outputLines.Append(myIO.GetCharArray(myClassA));
if (myClassA.MyClassBs != null)
myClassA.MyClassBs.ForEach(myClassB=>outputLines.Append(myClassB));
if (myClassA.MyClassCs != null)
myClassA.MyClassCs.ForEach(myClassC => outputLines.Append(myClassC));
}
if (append)
File.AppendAllText(filePath, outputLines.ToString());
else
File.WriteAllText(filePath, outputLines.ToString());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14838 次 |
| 最近记录: |