CsvHelper не пишет ничего в поток памяти
У меня есть следующий метод:
public byte[] WriteCsvWithHeaderToMemory<T>(IEnumerable<T> records) where T : class
{
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords<T>(records);
return memoryStream.ToArray();
}
}
Который вызывается со списком объектов - в конечном итоге из базы данных, но поскольку что-то не работает, я просто заполняю статическую коллекцию. Передаваемые объекты:
using CsvHelper.Configuration;
namespace Application.Models.ViewModels
{
public class Model
{
[CsvField(Name = "Field 1", Ignore = false)]
public string Field1 { get; set; }
[CsvField(Name = "Statistic 1", Ignore = false)]
public int Stat1{ get; set; }
[CsvField(Name = "Statistic 2", Ignore = false)]
public int Stat2{ get; set; }
[CsvField(Name = "Statistic 3", Ignore = false)]
public int Stat3{ get; set; }
[CsvField(Name = "Statistic 4", Ignore = false)]
public int Stat4{ get; set; }
}
}
То, что я пытаюсь сделать, это написать коллекцию в csv для загрузки в приложении MVC. Каждый раз, когда я пытаюсь написать метод, MemoryStream возвращается с нулевой длиной и ничего не передается ему. Я использовал это раньше, но по какой-то причине он просто не работает - я несколько смущен. Может ли кто-нибудь указать мне, что я сделал здесь неправильно?
ура
Ответы
Ответ 1
Поместите csvWriter.Flush();
перед возвратом, чтобы очистить устройство записи/поток.
ОБНОВЛЕНИЕ: в ответ на Джек. Должен быть сброшен поток, а не csvWriter. streamWriter.Flush();
. Оставив оригинальное решение, но добавив это исправление.
ОБНОВЛЕНИЕ 2: Мой предпочтительный ответ: fooobar.com/questions/5890096/... Пусть использование операторов сделает тяжелую работу для вас
Ответ 2
У вас уже есть, using
блок, который является большим. Это поможет вашему писателю. Вы можете просто немного изменить свой код, чтобы он работал.
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords<T>(records);
} // StreamWriter gets flushed here.
return memoryStream.ToArray();
}
Если вы включите AutoFlush
, вам нужно быть осторожным. Это будет сбрасываться после каждой записи. Если ваш поток является сетевым потоком и по кабелю, он будет очень медленным.
Ответ 3
Объединив все это (и комментарии для исправлений), включая сброс позиции потока памяти, окончательное решение для меня было;
using (MemoryStream ms = new MemoryStream())
{
using (TextWriter tw = new StreamWriter(ms))
using (CsvWriter csv = new CsvWriter(tw))
{
csv.WriteRecords(errors); // Converts error records to CSV
tw.Flush(); // flush the buffered text to stream
ms.Seek(0, SeekOrigin.Begin); // reset stream position
Attachment a = new Attachment(ms, "errors.csv"); // Create attachment from the stream
// I sent an email here with the csv attached.
}
}
В случае, если кто-то помог!
Ответ 4
В csvWriter нет флеша, флеш находится в streamWriter. Когда вызывается
csvWriter.Dispose();
он будет смывать поток. Другой подход - установить
streamWriter.AutoFlush = true;
который будет автоматически очищать поток каждый раз.
Ответ 5
Вот рабочий пример:
void Main()
{
var records = new List<dynamic>{
new { Id = 1, Name = "one" },
new { Id = 2, Name = "two" },
};
Console.WriteLine(records.ToCsv());
}
public static class Extensions {
public static string ToCsv<T>(this IEnumerable<T> collection)
{
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords(collection);
} // StreamWriter gets flushed here.
return Encoding.ASCII.GetString(memoryStream.ToArray());
}
}
}
На основании этого ответа.