Как ввести текст в определённую строчку текстового документа в 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 шт):
Чтобы что то вставить в текст(изменить его), вы считываете старый текст, меняете его на новый и записываете в файл(перезаписываете - удаляете и создаете с тем же именем)
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 любые буквы + новая линия, то мы можем создать сэмпл для строки, а затем вычислять её размер в байтах в зависимости от кодировки. Потом это кол-во байтов множим на позицию вставки и получаем необходимое смещение для вставки.
Начнём с критики.
Вы, когда пишете код, обращайте внимание на подсказки Студии (если, конечно, вы не пишете в Блокноте). И читайте документацию.
Вы написали:
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));