首页 > 解决方案 > 我需要手动刷新 StreamWriter 吗?

问题描述

我有以下情况。

我通过逐行读取巨大的 csv 文件来执行拆分功能。每行都有categoryId. 基于该 ID,我需要将此行写入单独的文件。

为此,我正在执行以下操作:

  1. 逐行读取巨大的文件。
  2. 阅读每一行后,我打开一个基于 categoryId 的新流(仅当流尚未打开时)。将行写入流,然后保持流打开,因为大文件中可能有更多行。
  3. 最后,处理完大文件中的所有行后,我将关闭所有打开的流。这会强制刷新并关闭连接。

我的问题是。我是否需要手动调用 Flush() 让我们说 -> 每记录 100 行,或者这是由 StreamWriter 本身处理的东西。我在网上读到有一个缓冲区满时会自动刷新,但我不确定这是否属实。我担心的是,如果它不刷新并等待大文件结束,我可能最终会将整个文件加载到内存中。

这是代码的一部分,看看在说什么:

try
        {
            while (!reader.EndOfStream)
            {
                var line = await reader.ReadLineAsync();
                var locationId = line.Split(',')[0];
                var gdProjectId = GetGDProjectId(locationId);

                var blobName = $"{gdProjectId}/{DateTime.UtcNow.ToString("dd-MM-yyyy")}/{DateTime.UtcNow.ToString("HH-mm-ss")}-{Guid.NewGuid()}.csv";

                if (!openWriters.ContainsKey(gdProjectId))
                {
                    var blockBlobClient = containerClient.GetBlockBlobClient(blobName);
                    var newWriteStream = await blockBlobClient.OpenWriteAsync(true);
                    openWriters.Add(gdProjectId, new StreamWriter(newWriteStream, Encoding.UTF8));
                }

                var writer = openWriters[gdProjectId];
                await writer.WriteLineAsync(line);

                // SHOULD I MANUALLY INVOKE FLUSH ON EVERY {X} lines processed ?
                // TODO: Check if we need to manually flush or the streamwriter does it for us when the buffer is full.
                // await writer.FlushAsync();
            }
        }
        catch (Exception ex)
        {

            throw;
        }
        finally
        {
            // we are always closing the writers no matter if the operation is successful or not.
            foreach (var oStream in openWriters)
            {
                oStream.Value.Close();
            }
        }

标签: c#.netstream

解决方案


Flush(在StreamWriter实现中)只是将数据从缓冲区发送到底层流,然后调用Flush底层流,即(伪代码):

underlyingStream.Write(GetDataFromBuffer());
bufferPosition = 0; // "clears" buffer
underlyingStream.Flush();

缓冲区大小是恒定的。默认情况下,它大约是 2-4KiB。但可以在构造函数中手动设置更大的值。Flush不改变缓冲区大小。Flush因此,每 100 行调用一次不会给您任何帮助。

问:“我是否需要手动调用 Flush() 让我们说 -> 每 100 行...”

不,它不会为您节省任何记忆。它只会更早地将数据写入底层流 - 即它不会等待缓冲区已满。
提示:如果属性AutoFlush设置为 true,Flush将在每次 WriteXYZ 方法调用后自动调用。

问:“我担心的是,如果它不刷新并等待大文件结束,我可能最终会将整个文件加载到内存中。”

缓冲区大小是恒定的。打电话Flush也无济于事。

但...

仅从角度来看,一切都是真实的StreamWriter
因为StreamWriter只持有对某个Stream实例的引用,所以如果不知道该Stream实例的具体实现(Streamis abstract),您就无法预测内存使用情况。

您应该创建新问题,例如:“我需要手动刷新 XyzStream”吗?(如果没有已经发布的问题)。


推荐阅读