Как удалить все строки в текстовом файле под определенным текстом? - PullRequest
1 голос
/ 02 июня 2019

У меня есть код, который перебирает весь текстовый файл в поисках определенного текста «[имена]» и «пытался» удалить все строки под текстом. Я попытался File.WriteAllText (INILoc, string.Empty); но это просто удаляет все во всем текстовом файле. Как сделать так, чтобы удалялись только все строки ниже "[names]"?

Я настроил итерацию следующим образом:

string[] lines = File.ReadAllLines(INILoc);
bool containsSearchResul = false;
foreach (string line in lines)
    {
         if (containsSearchResul)
           {
                File.WriteAllText(INILoc, string.Empty);

           }
         if (line.Contains("[names]"))
           {
                containsSearchResul = true;
           }
    }

Ответы [ 5 ]

1 голос
/ 02 июня 2019

Используйте StreamReader, поскольку это даст вам наилучшую производительность, так как вам не нужно читать весь файл. Поменяйте местами «PATH TO INPUT FILE» с вашим путем к файлу, и результат будет сохранен по пути, который вы указали для «PATH TO OUTPUT FILE».

using (var sr = new StreamReader("PATH TO INPUT FILE"))
{
    using (var sw = new StreamWriter("PATH TO OUTPUT FILE"))
    {
        var line = sr.ReadLine();

        while (line != null)
        {
            sw.WriteLine(line);

            if (line.Contains("[names]"))
            {
                sw.Close();
                sr.Close();
            }
            else
            {                            
                line = sr.ReadLine();
            }                        
        }
    }
}

Если вам нужно записать в тот же файл:

var sb = new StringBuilder();

using (var sr = new StreamReader("PATH TO INPUT FILE"))
{
    var line = sr.ReadLine();

    while (line != null)
    {
        sb.AppendLine(line);

        if (line.Contains("[names]"))
        {
            sr.Close();
        }
        else
        {
            line = sr.ReadLine();
        }
    }
}

File.WriteAllText("PATH TO INPUT FILE", sb.ToString());
1 голос
/ 02 июня 2019

Вам нужно сохранить строки перед "[names]" текстом в строковую переменную, а когда условие (line.Contains("[names]")) удовлетворяет, просто разорвать цикл и записать строковое значение в один и тот же файл.

Что-то вроде,

string[] lines = File.ReadAllLines(INILoc); //Considering INILoc is a string variable which contains file path.
StringBuilder newText = new StringBuilder();
bool containsSearchResul = false;

foreach (string line in lines)
    {
       newText.Append(line);
       newText.Append(Environment.NewLine); //This will add \n after each line so all lines will be well formatted

       //Adding line into newText before if condition check will add "name" into file
       if (line.Contains("[names]"))
              break;

    }

File.WriteAllText(INILoc, newText.ToString());
                        //^^^^^^^ due to string.Empty it was storing empty string into file.

Примечание: Если вы используете StringBuilder класс, то не пропустите добавление Using System.Text в вашу программу

0 голосов
/ 02 июня 2019

Вы также можете использовать: WriteAllLines(string path, IEnumerable<string> contents) вот так:

string[] lines = File.ReadAllLines(INILoc);
List<string> linesToWrite = new List<string>();

foreach(string line in lines)
{
    linesToWrite.Add(line);
    if (line.Contains("[names]")) break;
}

File.WriteAllLines(INILoc, linesToWrite);
0 голосов
/ 02 июня 2019

На основании запрошенного кода я собрал модификации.

    string[] lines = File.ReadAllLines(INILoc);
    //create a list to hold the lines
    List<string> output = new List<string>();
    //loop through each line
    foreach (string line in lines)
    {
        //add current line to  ouput.
        output.Add(line);
        //check to see if our line includes the searched text;
        if (line.Contains("[names]"))
        {
            //output to the file and then exit loop causing all lines below this 
            //one to be skipped
            File.WriteAllText(INILoc, output.ToArray());
            break;
        }
    }
0 голосов
/ 02 июня 2019

Проблема с вашим кодом заключается в том, что он удаляет все строки до [names], а не после (точнее, пишите только строки после этого текста).Кроме того, каждый раз, когда вы переписываете все содержимое файла и удаляете всю предыдущую строку записи.Это будет работать следующим образом:

string[] lines = File.ReadAllLines(INILoc);
using (StreamWriter writer = new StreamWriter(INILoc)) // https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-write-text-to-a-file
{
            bool containsSearchResul = false;
            foreach (string line in lines)
            {

                if (!containsSearchResul)
                {
                    writer.Write(INILoc, string.Empty);

                }

                if (line.Contains("[names]"))
                {
                    containsSearchResul = true;
                }
            }
}

У вас есть другой, лучший вариант сделать это с помощью break:

string[] lines = File.ReadAllLines(INILoc);
using (StreamWriter writer = new StreamWriter(INILoc)) // https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-write-text-to-a-file
{
            foreach (string line in lines)
            {
                if (line.Contains("[names]"))
                {
                    break;
                }

                writer.WriteLine(INILoc, string.Empty);
            }
}

Но вы можете сделать это предпочтительным, более читабельнымКстати, с помощью LINQ:

using System.Linq;

// ...

string[] lines = File.ReadAllLines(INILoc);
string[] linesTillNames = lines
                          .Take( // Take just N items from the array
                              Array.IndexOf(lines, "[names]") // Until the index of [names]
                          )
                          .ToArray();
File.WriteAllLines(INILoc, linesTillNames);
...