Перезапись файла с помощью StreamWriter C#

Есть проблема Определён StreamReader

using (StreamReader reader = new StreamReader(PathManager.PathUserID))

В этом using есть другой блок using

using (StreamWriter write = new StreamWriter(PathManager.PathUserID))
{
    List<string> userID = new List<string>();
    while ((ID = reader.ReadLine()) != null)
    {
        if (ID == message.Chat.Id.ToString())
        { continue; }
        userID.Add(ID);
    }
    write.Write(string.Join(Environment.NewLine, userID));
}

Смысл такой: Имеется файл с ID пользователей по полю PathManager.PathUserID Блок с StreamWriter write вызывается тогда, когда пользователь хочет отписаться от рассылки, должно происходить это следующим образом: Список userID нужен для того, чтобы добавить все ID в него из файла, кроме ID того пользователя, который хочет отписаться это как раз делает блок while, когда видит совпадающие ID, он его просто не добавляет В конце всё записывается в файл с переносом строки с помощью write.Write(string.Join(Environment.NewLine, userID)); Но происходит просто удаление всех записей из файла и всё Как исправить данную проблему?


Ответы (1 шт):

Автор решения: Alexander Petrov

У файловых потоков есть множество параметров, такие как FileShare, FileAccess и другие. Чтобы один и тот же поток (stream) мог одновременно использоваться разными читателями/писателями, нужно правильно задать эти параметры.
Минимум нужно указать следующее: reader разрешает (расшаривает доступ) другим средствам писать (FileShare.Write) в этот же поток, а writer'у нужно явно задать доступ на запись (FileAccess.Write).

string? line;
using (StreamReader reader = new StreamReader(path, new FileStreamOptions { Share = FileShare.Write }))
using (StreamWriter writer = new StreamWriter(path, new FileStreamOptions { Access = FileAccess.Write }))
{
    List<string> ids = new List<string>();
    while ((line = reader.ReadLine()) != null)
    {
        if (line != value)
            ids.Add(line);
    }
    writer.Write(string.Join(Environment.NewLine, ids));
}

Однако, если получившийся результат будет короче исходного содержимого, то в конце файла останется мусор. К тому же может влиять наличие BOM...
Подробное описание вы явно воспримете как rocket science, а вы, судя по уже удалённым комментариям, не стремитесь к звёздам.


Гораздо проще поступить следующим образом: открываем поток на чтение, полностью читаем, закрываем, открываем поток на запись, пишем, закрываем.
При это нет необходимости задумываться о правилах расшаривания и доступа, не будет лишнего мусора.

string? line;
List<string> ids = new List<string>();

using (StreamReader reader = new StreamReader(path))
{
    while ((line = reader.ReadLine()) != null)
    {
        if (line != value)
            ids.Add(line);
    }
}
using (StreamWriter writer = new StreamWriter(path))
{
    writer.Write(string.Join(Environment.NewLine, ids));
}

Я бы предложил более простой способ:

var ids = File.ReadLines(path).Where(line => line != value).ToList();

File.WriteAllLines(path, ids);

но вы явно воспримете его как критику своего кода, что вы не любите...

→ Ссылка