簡體   English   中英

C# 重用 StreamWriter 或 FileStream 但更改目標文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM