Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我需要手动刷新StreamWriter吗?_C#_.net_Stream - Fatal编程技术网

C# 我需要手动刷新StreamWriter吗?

C# 我需要手动刷新StreamWriter吗?,c#,.net,stream,C#,.net,Stream,我有下面的场景 我通过逐行读取巨大的csv文件来实现拆分功能。 每行都有类别ID。 基于该Id,我需要将这一行写入单独的文件 为此,我将执行以下操作: 逐行读取巨大的文件 在阅读每一行之后,我根据categoryId打开一个新的流(仅当流尚未打开时)。将行写入流中,然后保持流处于打开状态,因为在这个巨大的文件中可能会有更多行 在处理完大文件中的所有行之后,我将关闭所有打开的流。这将强制冲洗并关闭连接 我的问题是。我是否需要手动调用Flush(),比如->每记录100行,或者这是StreamWri

我有下面的场景

我通过逐行读取巨大的csv文件来实现拆分功能。 每行都有
类别ID
。 基于该Id,我需要将这一行写入单独的文件

为此,我将执行以下操作:

  • 逐行读取巨大的文件
  • 在阅读每一行之后,我根据categoryId打开一个新的流(仅当流尚未打开时)。将行写入流中,然后保持流处于打开状态,因为在这个巨大的文件中可能会有更多行
  • 在处理完大文件中的所有行之后,我将关闭所有打开的流。这将强制冲洗并关闭连接
  • 我的问题是。我是否需要手动调用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();
                }
            }
    
    Flush
    (在
    StreamWriter
    实现中)只需将数据从缓冲区发送到底层流,然后对底层流调用
    Flush
    ,即(伪代码):

    缓冲区大小为常量。默认情况下,它大约是2-4KB。但对于较大的值,可以在构造函数中手动设置<代码>刷新不会更改缓冲区大小。因此,每100行调用
    Flush
    不会给您带来任何好处

    Q:“我是否需要手动调用Flush(),比如->每100行…”

    不会。它不会为您节省任何内存。它只会更早地将数据写入底层流,也就是说,它不会等待缓冲区已满。
    Hint:如果属性
    AutoFlush
    设置为true,则每次调用WriteXYZ方法后将自动调用
    Flush

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

    缓冲区大小是恒定的。调用
    Flush
    没有帮助

    但是

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


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

    始终发布代码而不是图像。有时人们想复制一些代码并将其放入他们的答案中。在完成编写之前,您绝对不想调用Flush()。这样做会导致缓冲区在满之前被刷新,从而破坏缓冲区的用途。在写入所有数据后显式调用Flush()是一种很好的做法,但是如上所述,退出using{}块将隐式地执行此操作。我更喜欢显式地调用它,因为如果写入底层流时出现异常,诊断起来会更容易一些。嘿,伙计们,我用代码而不是屏幕截图更新了我的示例@glenebob我的问题是streamWriter是否以及何时调用自动刷新?我想象一下,如果缓冲区是1024->在它满后,它会自动刷新并写入目标流,对吗?我关心的是不要在内存中加载太多数据,并消耗机器的整个RAM。在自动刷新之前,你知道我可以在writer中放入多少个字符吗?我将处于这样一种情况:我可以同时拥有许多开放流,我不想消耗所有的ram。“我不想消耗所有的ram”-你无法控制。即使您调用
    Flush()
    ,并且即使
    StreamWriter.Flush()
    方法显式刷新底层流,文件I/O中也有更多的层,例如操作系统缓存。更重要的是,这些缓冲区只有K个大的数目;它们太小了,不会对内存开销产生任何实质性影响,即使它们确实存在,缓冲区也会存在,无论是否刷新。显式调用
    Flush()
    的唯一原因是当您有特定的原因来确保数据已。。。。。。已写入,例如,您正在写入网络流,不希望数据延迟,或者正在写入日志文件,希望确保每一行都已写入,以防进程崩溃,诸如此类。还要注意的是@jdweng上面的评论大多是错误的。没有计时器,关闭写入程序时不需要调用
    Flush()
    ,因为关闭/处理写入程序将始终自动刷新数据,这是该操作的一部分。感谢您提供详细答案!我正在使用azure blob存储流。我注意到,即使尝试将缓冲区大小更改为4096(例如),当我检查缓冲区大小时仍然是4194304。我猜他们的流实现不允许我更改缓冲区。无论如何,谢谢你的建议来改变我的问题。我将首先尝试谷歌,并明确表示我使用的是blob存储流。如果找不到更多信息,我将在这里打开另一个问题。在您的推荐之后,我做了一些研究,发现azure blob流的缓冲区大小有不同的最小值、最大值和默认值。默认值为4MB,最大值为4000MB,最小值为1MB。下面是我如何配置它的。var newWriteStream=await blockBlobClient.OpenWriteAsync(true,new Azure.Storage.Blobs.Models.BlockBlobOpenWriteOptions{BufferSize=1048576});这回答了我的问题,为什么我不能强制缓冲区先前写入到结束流->因为我是sen
    underlyingStream.Write(GetDataFromBuffer());
    bufferPosition = 0; // "clears" buffer
    underlyingStream.Flush();