Как ввести текст в определённую строчку текстового документа в c#

Как вставить текст в .txt документ, но при этом в определённую строчку? В первом случае надо например на 2-ую строку, не заменяя старое. Во втором под строчку с определённым текстом, так же не заменяя старый текст. Вот актуальный код на запись.

StreamWriter writer = new StreamWriter(testforwrite, false, System.Text.Encoding.Default);
writer.WriteLine("Тест")
write.Close();

Например, есть текстовый документ и в нём текст:

aaa
bbb
ccc
ddd

Нужно, чтобы текст вставился между строками в 1 случае:

aaa
bbb
ccc
DDD
ddd

А во 2-ом перед определённой строчкой, содержащей bbb

aaa
DDD
bbb
ccc
ddd

Вот неработающий второй код:

string path = "modlist.txt";

string item = "MOD"; // что вставляем

var lines = File.ReadAllLines(path).ToList();

string target = "+"; // по идеи ищет + в txt файле

int index = lines.FindIndex(s => s == target); 

lines.Insert(index, item); // должен добавить текст MOD перед строкой с "+", но ничего не происходит


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

Автор решения: Pavlo Khyzhniak

Чтобы что то вставить в текст(изменить его), вы считываете старый текст, меняете его на новый и записываете в файл(перезаписываете - удаляете и создаете с тем же именем)

→ Ссылка
Автор решения: return
static readonly string rowSmpl = "xxx" + Environment.NewLine;

static void InsertString(string path, int position, string str, Encoding? encoding = null)
{
    // checks skipped

    encoding ??= Encoding.Default;

    using var stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite);
    using var reader = new StreamReader(stream, encoding);
    using var writer = new StreamWriter(stream, encoding)
    {
        AutoFlush = true
    };
    var tmpPath = Path.GetTempPath() + Guid.NewGuid().ToString() + ".tmp";
    using var tmpStream = File.Open(tmpPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
    using var tmpReader = new StreamReader(tmpStream, encoding);
    using var tmpWriter = new StreamWriter(tmpStream, encoding, 1024)
    {
        AutoFlush = true
    };

    var rowLen = encoding.GetByteCount(rowSmpl);
    var seekOffs = rowLen * position;
    stream.Seek(seekOffs, SeekOrigin.Begin);

    Span<char> buf = stackalloc char[1024];

    do
    {
        var bufLen = reader.ReadBlock(buf);

        tmpWriter.Write(buf[..bufLen]);
    } while (stream.Position != stream.Length);

    stream.Seek(seekOffs, SeekOrigin.Begin);
    writer.WriteLine(str);

    tmpStream.Seek(0, SeekOrigin.Begin);

    do
    {
        var bufLen = tmpReader.ReadBlock(buf);

        writer.Write(buf[..bufLen]);
    } while (tmpStream.Position != tmpStream.Length);

    tmpWriter.Close();
    File.Delete(tmpPath);
}

Как это работает? Нам нужно вставить строку, т. е. нам нужно как-то скопировать данные после места вставки вперёд, а затем вписать строку в это же место вставки. Для этого мы берём и создаём временный .tmp файл в который записываем часть после места вставки. Затем записываем нашу строку, а после этого читаем данные из временного файла и записываем их в файл поверх строки. Временный файл удаляем.

Т. к. формат строк такой: 3 любые буквы + новая линия, то мы можем создать сэмпл для строки, а затем вычислять её размер в байтах в зависимости от кодировки. Потом это кол-во байтов множим на позицию вставки и получаем необходимое смещение для вставки.

→ Ссылка
Автор решения: Alexander Petrov

Начнём с критики.

Вы, когда пишете код, обращайте внимание на подсказки Студии (если, конечно, вы не пишете в Блокноте). И читайте документацию.

Вы написали:

StreamWriter writer = new StreamWriter(testforwrite, false, System.Text.Encoding.Default);

Первым параметром в конструкторе StreamWriter идёт путь (имя файла). Так дайте ему осмысленное название. Например, общепринятые path или filename.

Второй параметр - append: false означает переписать файл. То есть всё предыдущее содержимое будет потеряно. Просто читайте документацию к используемым классам!

Третье. Никогда не используйте кодировку Default! На каждом компьютере она своя. В итоге файл, записанный вашей программой на одном компьютере, может не открыться (выдать кракозябры) вашей же программой на другом компьютере.

Укажите какую-либо конкретную кодировку. Если файл предназначен для использования только в вашей программе, то Encoding.Unicode, если будет передаваться куда-либо (по сети) для использования в других программах, то Encoding.UTF8.


Приведу самые простые способы решения ваших задач.

Используем методы класса File. Читаем и записываем файл с их помощью.

Считанный массив преобразуем в List - этот класс имеет удобный метод Insert, выполняющий нужную нам работу.

string path = "test.txt";

string item = "DDD"; // что вставляем
        
var lines = File.ReadAllLines(path).ToList();

int index = 3; // после какой строки вставлять
lines.Insert(index, item);

File.WriteAllLines(path, lines);

Для второй задачи опять же используем метода класса List. С его помощью находим индекс строки, перед которой потом сделаем вставку.

string target = "bbb";
int index = lines.FindIndex(s => s == target);
lines.Insert(index, item);

Если текст, который ищем, расположен не на отдельной строке, а содержится в ней, то меняем сравнение:

int index = lines.FindIndex(s => s.Contains(target));
→ Ссылка