C# StreamWriter 写入 MemoryStream
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11147491/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
StreamWriter writing to MemoryStream
提问by ediblecode
I was under the impression that when you called Flush()in a StreamWriter object it writes to the underlying stream, but apparently this isn't the case with my code.
我的印象是,当您调用Flush()StreamWriter 对象时,它会写入底层流,但显然我的代码并非如此。
Instead of writing to my file it will just write nothing. Any ideas where I'm going wrong?
它不会写入我的文件,而不会写入任何内容。任何想法我哪里出错了?
public FileResult DownloadEntries(int id)
{
Competition competition = dataService.GetCompetition(id);
IQueryable<CompetitionEntry> entries = dataService.GetAllCompetitionEntries().Where(e => e.CompetitionId == competition.CompetitionId);
MemoryStream stream = new MemoryStream();
StreamWriter csvWriter = new StreamWriter(stream, Encoding.UTF8);
csvWriter.WriteLine("First name,Second name,E-mail address,Preferred contact number,UserId\r\n");
foreach (CompetitionEntry entry in entries)
{
csvWriter.WriteLine(String.Format("{0},{1},{2},{3},{4}",
entry.User.FirstName,
entry.User.LastName,
entry.User.Email,
entry.User.PreferredContactNumber,
entry.User.Id));
}
csvWriter.Flush();
return File(stream, "text/plain", "CompetitionEntries.csv");
}
采纳答案by David Thielen
I believe you need to set Stream.Position = 0. When you write, it advances the position to the end of the stream. When you pass it to File()it starts from the position it is at - the end.
我相信你需要设置Stream.Position = 0. 当您写入时,它会将位置推进到流的末尾。当你将它传递给File()它时,它从它所在的位置开始 - 结束。
I think the following will work (did not try to compile this):
我认为以下将起作用(没有尝试编译它):
stream.Position = 0;
return File(stream, "text/plain", "CompetitionEntries.csv");
And this way you are not creating any new objects or copying the underlying array.
这样您就不会创建任何新对象或复制底层数组。
回答by Alexei Levenkov
Your MemoryStream is positioned at the end. Better code would be to create new R/o memory stream on the same buffer using MemoryStream(Byte[], Int32, Int32, Boolean)constructor.
您的 MemoryStream 位于末尾。更好的代码是使用MemoryStream(Byte[], Int32, Int32, Boolean)构造函数在同一缓冲区上创建新的 R/o 内存流。
Simplest r/w on trimmed buffer:
修剪缓冲区上最简单的 r/w:
return File(new MemoryStream(stream.ToArray());
R/o without copying the internal buffer:
R/o 不复制内部缓冲区:
return File(new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length, false);
Note: be careful not to dispose the stream you are returning via File(Stream). Otherwise you'll get "ObjectDisposedException" of some sort. I.e. if you simply set position of the original stream to 0 and wrap StreamWriter into using you'll get into returning disposed stream.
注意:注意不要处理您通过 File(Stream) 返回的流。否则你会得到某种“ObjectDisposedException”。即,如果您只是将原始流的位置设置为 0 并将 StreamWriter 包装为 using,您将进入返回已处理的流。
回答by neontapir
In playing with this, I got the following prototype to work:
在玩这个时,我得到了以下原型:
using System.Web.Mvc;
using NUnit.Framework;
namespace StackOverflowSandbox
{
[TestFixture]
public class FileStreamResultTest
{
public FileStreamResult DownloadEntries(int id)
{
// fake data
var entries = new[] {new CompetitionEntry { User = new Competitor { FirstName = "Joe", LastName = "Smith", Email = "[email protected]", Id=id.ToString(), PreferredContactNumber = "555-1212"}}};
using (var stream = new MemoryStream())
{
using (var csvWriter = new StreamWriter(stream, Encoding.UTF8))
{
csvWriter.WriteLine("First name,Second name,E-mail address,Preferred contact number,UserId\r\n");
foreach (CompetitionEntry entry in entries)
{
csvWriter.WriteLine(String.Format("{0},{1},{2},{3},{4}",
entry.User.FirstName,
entry.User.LastName,
entry.User.Email,
entry.User.PreferredContactNumber,
entry.User.Id));
}
csvWriter.Flush();
}
return new FileStreamResult(new MemoryStream(stream.ToArray()), "text/plain");
}
}
[Test]
public void CanRenderTest()
{
var fileStreamResult = DownloadEntries(1);
string results;
using (var stream = new StreamReader(fileStreamResult.FileStream))
{
results = stream.ReadToEnd();
}
Assert.IsNotEmpty(results);
}
}
public class CompetitionEntry
{
public Competitor User { get; set; }
}
public class Competitor
{
public string FirstName;
public string LastName;
public string Email;
public string PreferredContactNumber;
public string Id;
}
}

