StreamReader.ReadLine() 不消耗流

Posted

技术标签:

【中文标题】StreamReader.ReadLine() 不消耗流【英文标题】:StreamReader.ReadLine() doesn't consume the stream 【发布时间】:2018-03-16 07:36:55 【问题描述】:

我正在启动一个新的 Web 应用程序项目,用户可以在其中上传 .csv 文件,以便我可以处理该文件。

目前我可以让用户上传文件,但是当我尝试使用StreamReader 从文件生成的流中读取时,StreamReader 似乎无法从流中正确读取。

顺便说一下,上传文件部分我是按照微软教程here

这是视图的代码。

<form method="post" enctype="multipart/form-data" asp-controller="Upload" asp-action="Upload">
<div class="form-group">
    <div class="col-md-10">
        <p>Upload one or more files using this form:</p>
        <input type="file" name="files" >
    </div>
</div>
<div class="form-group">
    <div class="col-md-10">
        <input type="submit" value="Upload" />
    </div>
</div>

这是我的控制器代码

len、len2 和 p 是用于调试目的的变量。

[HttpPost]
    public async Task<IActionResult> Upload(IFormFile file)
    
        if (file != null && file.Length > 0)
        
            var filePath = Path.GetTempFileName(); //Note: May throw excepetion when temporary file exceeds 65535 per server
            var stream = new FileStream(filePath, FileMode.Create);
            await file.CopyToAsync(stream);//
            long len = stream.Length;// 412 bytes
            StreamReader reader = new StreamReader(stream);//*
            int p = reader.Peek();//currently the next character is EoF
            var val = reader.ReadLine();
            long len2 = stream.Length;// 412 bytes
            bool end = reader.EndOfStream;// true

            //do some stuff here

            return RedirectToAction("Success");
        
        else
        
            return RedirectToAction("Upload_fail");//file not found
        
    

我们将不胜感激任何建议或帮助。

【问题讨论】:

尝试在将流加载到阅读器之前将其位置重置为 0。 stream.Position = 0 @Kyle 感谢您的建议,这确实有效。所以我想知道是什么导致该位置移动到文件末尾? 【参考方案1】:

从 Stream 读取时,当前位置会相应更新。例如,想象以下步骤:

    位置从 0 开始(流的开头)。 读取单个字节 - 这会将位置更新为 1。 读取另一个字节 - 这会将位置更新为 2。

如果流中只有两个字节,则位置现在被视为EOF - 不再可能读取其他字节,因为它们已经被读取。

与您的示例相关,对await file.CopyToAsync(stream) 的调用将流的位置推进到EOF。因此,当您将StreamReader 包裹起来时,就没有什么可读的了。写入的过程是相同的 - CopyToAsync 操作正在推进输入和输出流,导致一旦操作完成,两个流都位于 EOF。

让事情稍微复杂一点的是,Streams 可以是仅向前的,这意味着一旦读取数据就不可能向后返回。当您使用FileStream 时,我认为您可以回到开头,如下所示:

await file.CopyToAsync(stream);
stream.Position = 0;

您也可以使用stream.Seek(0, SeekOrigin.Begin),如本答案所述:Stream.Seek(0, SeekOrigin.Begin) or Position = 0

【讨论】:

以上是关于StreamReader.ReadLine() 不消耗流的主要内容,如果未能解决你的问题,请参考以下文章

Resolve StreamReader ReadLine left the first character

Resolve StreamReader ReadLine left the first character

Streamreader readline从流程执行返回空值[重复]

.net StreamReader .Readline报内存溢出OutOfMemory,求助!!

C#将文本拆分为子字符串

C# 动态类型 以及 脚本调用(scriptRunTime)