[英]C# Reuse StreamWriter or FileStream but change destination file
一点背景...
我将要描述的直到实现 StreamWriter 的所有内容都是我无法更改的业务流程。
每个月我都会将大约 200 个不同的数据表提取到单独的文件中。 每个文件包含大约 400,000 行业务逻辑详细信息,用于超过 5,000-6,000 个不同的业务单元。
为了通过手头的工具有效地使用这些数据,我必须将这些文件分解为每个业务部门的单独文件......
每个文件 200 个文件 x 5000 个业务单位 = 100,000 个不同的文件。
我一直在做的方式是典型的 StreamWriter 循环......
foreach(string SplitFile in List<BusinessFiles>)
{
using (StreamWriter SW = new StreamWriter(SplitFile))
{
foreach(var BL in g)
{
string[] Split1 = BL.Split(',');
SW.WriteLine("{0,-8}{1,-8}{2,-8}{3,-8}{4,-8}{5,-8}{6,-8}{7,-8}{8,-8}{9,-16}{10,-1}",
Split1[0], Split1[1], Split1[2], Split1[3], Split1[4], Split1[5], Split1[6], Split1[7], Split1[8], Convert.ToDateTime(Split1[9]).ToString("dd-MMM-yyyy"), Split1[10]);
}
}
}
这样做的问题是,它需要过多的时间。 比如,有时处理所有文件可能需要 20 分钟。
分析我的代码显示,98% 的时间都花在了程序离开循环后系统处理 StreamWriter 上。
所以我的问题是......
有没有办法保持底层 Stream 打开并重用它来编写不同的文件?
我知道我可以 Flush() Stream 但我不知道如何让它开始完全写入另一个文件。 我似乎找不到无需调用另一个 StreamWriter 即可更改目标文件名的方法。
编辑:
这听起来很对。 20 分钟内 100,000 个文件超过每秒 83 个文件。 磁盘 I/O 几乎是您在单台计算机中可以做的最慢的事情。 Dispose()
方法中的所有时间都是在关闭文件时等待缓冲区刷新到磁盘...这是将数据写入持久存储的实际时间,并且每个文件的单独using
块是正确的方法以确保安全完成。
为了加快速度,很想看看异步处理(async/await),但我认为你不会在那里找到任何收获; 归根结底,这是一个 I/O 密集型任务,因此针对 CPU 调度进行优化甚至可能使事情变得更糟。 如果您可以将 output 更改为写入单个(索引)文件,则可以获得更好的收益,因此操作系统的磁盘缓冲机制可以更有效。
回答您的问题,您有一个选项(在构造函数上添加一个标志),但它与垃圾收集器密切相关,还要考虑多线程环境,它可能会一团糟。 也就是说这是重载的构造函数:
StreamWriter(流,编码,Int32,布尔值)
使用指定的编码和缓冲区大小为指定的 stream 初始化 StreamWriter class 的新实例,并可选择将 stream 保持打开状态。
public StreamWriter (System.IO.Stream stream, System.Text.Encoding? encoding = default, int bufferSize = -1, bool leaveOpen = true);
我同意 Joel 的观点,时间主要是因为将数据写入磁盘。 但是,我对并行 IO 会更乐观一些,因为 SSD 比普通 HDD 能够更好地处理更高的负载。 所以我会尝试一些事情:
1.并行做事
将您的外循环更改为并行循环
Parallel.ForEach(
myBusinessFiles,
new ParallelOptions(){MaxDegreeOfParallelism = 2},
SplitFile => {
// Loop body
});
尝试更改并行度以查看性能是否有所提高。 这假设数据是线程安全的。
2.尝试写入高速本地SSD
我假设您正在写入网络文件夹,这会增加一些额外的延迟,因此您可能会尝试写入本地磁盘。 如果您已经这样做了,请考虑获得更快的磁盘。 如果您之后需要将所有文件移动到网络驱动器,您可能不会获得任何东西,但它可以让您了解您从网络中获得的惩罚。
3. 尝试写入 Zip 存档
有zip 档案可以在其中包含多个文件,同时仍然允许相当容易地访问单个文件。 这可以通过以下几种方式帮助提高性能:
您也可以尝试将每个文件保存在单独的 zip 存档中,但这样您将主要从压缩中受益。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.