MemoryStream приносит половину данных при создании строки CSV

У меня действительно простой вопрос, но поиск решения занимает много времени. Все равно не нашел и решил написать сюда. Ниже приведен код для получения строки в формате CSV. Но проблема в том, что данные CSV сокращены до 1020 символов. Просто верхние 1020 символов отображаются только в переменной «csvString».

var records = new List<CSVDto>();
//In here Assign data to records 

var csvConfig = new CsvConfiguration(CultureInfo.InvariantCulture)
{
    HasHeaderRecord = true,
    Delimiter = ","
};

using (var mem = new MemoryStream())
{
    using (var writer = new StreamWriter(mem))
    {
        using (var csvWriter = new CsvWriter(writer, csvConfig))
        {
            await csvWriter.WriteRecordsAsync(records);
            var csvString = Encoding.UTF8.GetString(mem.ToArray()); //im getting only first 1020 characters.                              
        }
        await writer.FlushAsync();
    }
}

У кого-нибудь из экспертов есть идеи о том, что не так с этим кодом? Как получить полный CSV с объектом «записи»? Я ценю ваш достойный ответ по этому поводу.

Вы звоните mem.ToArray() до того, как закрыли csvWriter или очистили writer... по какой причине вы делаете это там, а не после вызова FlushAsync?

Jon Skeet 13.09.2023 15:30

Попробуйте вызвать var csvString = Encoding.UTF8.GetString(mem.ToArray()); после закрытия MemoryStream.

Jack Miller 13.09.2023 15:30

Если вам нужна строка, почему бы не использовать StringWriter? Если вы хотите сохранить данные на диске, зачем использовать MemoryStream вместо FileStream?

Panagiotis Kanavos 13.09.2023 15:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Прежде чем пытаться считать результат из MemoryStream, вам следует сначала очистить/закрыть средства записи.

using (var mem = new MemoryStream())
{
    using (var writer = new StreamWriter(mem))
    {
        using (var csvWriter = new CsvWriter(writer, csvConfig))
        {
            await csvWriter.WriteRecordsAsync(records);
        }
        await writer.FlushAsync(); // not actually needed, since closing the writer (end of using block) will also trigger flushing
    }
    var csvString = Encoding.UTF8.GetString(mem.ToArray()); // <- should contain all data now
}

Это работает. Спасибо, 7he3rain.

weeraa 18.09.2023 19:21
using var mem = new MemoryStream();
using var writer = new StreamWriter(mem);
using var csvWriter = new CsvWriter(writer, csvConfig);

await csvWriter.WriteRecordsAsync(records);

// Flush the CsvWriter and StreamWriter to ensure all data is written to the MemoryStream.
await csvWriter.FlushAsync();
await writer.FlushAsync();

// Go back to the beginning of the MemoryStream before reading it.
// NOTE: this is not required for .ToArray; but you get the idea.
// It is required if you were going to read from the MemoryStream as a stream. 
// So we include this line as a reminder to do the right thing.
// This is especially useful on SO if you're here to solve a problem
// relating to unflushed buffers - even though you're not using .ToArray.
// Also it's good practice to do it because 
// good programmers look both ways before crossing a one-way street.
mem.Position = 0;

var csvString = Encoding.UTF8.GetString(mem.ToArray());

С этим ответом связано несколько проблем: (а) mem.Position = 0 не требуется для получения содержимого с помощью mem.ToArray(). (б) Он не скомпилируется, потому что using требуются скобки для объявления переменной и блок для того, что должно произойти перед удалением объекта. (c) Любые объекты, реализующие IDisposable, следует по возможности помещать в блок using. Никогда не создавайте одноразовые предметы и не позволяйте им «висеть», не выбрасывая и не возвращая их.

7he3rain 13.09.2023 16:58

@7he3rain Вы предлагаете использовать var mem = new MemoryStream(); неверный синтаксис, который не вызывает Dispose() на объекте MemoryStream? Вы подразумеваете, что единственный правильный синтаксис using — это using (var mem = new MemoryStream()) { ...code that uses the memory stream... }?

Ian Boyd 13.09.2023 17:58

Сначала я подумал, что это может быть правильный синтаксис, но «бессмысленный», поскольку объект будет удален в том же операторе, что и создан. Но на самом деле он даже не компилируется. Однако using (var mem = new MemoryStream()); немедленно компилирует и удаляет объект, но также приводит к тому, что переменная mem сразу выходит за пределы области видимости, поэтому на следующей строке с new StreamWriter(mem) произойдет сбой.

7he3rain 13.09.2023 18:12
using (var mem = new MemoryStream()); — неправильный синтаксис. Вам нужно использовать синтаксис C# using: using var mem = new MemoryStream();
Ian Boyd 13.09.2023 19:54

Хорошо, я потратил некоторое время на изучение этого вопроса, и синтаксис @ian-boyd ДЕЙСТВИТЕЛЬНО работает, но ТОЛЬКО в C# 8 и выше. Я все еще использую Visual Studio 2019, которая, видимо, еще не поддерживает этот синтаксис. Лично мне не нравится новый/добавленный синтаксис using, потому что он скрывает время жизни одноразового объекта и усложняет понимание кода. Определенно не помогает, когда вы пытаетесь объяснить кому-то здесь, почему их код не работает (особенно, если опубликованный исходный код НЕ использует новый синтаксис).

7he3rain 13.09.2023 20:12

Другие вопросы по теме