【问题标题】:Find specific text in a file and replace that在文件中查找特定文本并将其替换
【发布时间】:2012-12-10 11:20:04
【问题描述】:

我正在构建一个 WPF 程序,该程序正在编辑模拟程序的保存文件,以便更轻松地调整某些参数。该(txt)文件的结构如下所示

{Verdieping 1}

A bunch of data

'Max'
15
20
10
]);

More data

{Verdieping 2}

A bunch of data

'Max'
25
10
40
20
]);

More data

{Verdieping 3}

etc.

因为我需要的列表名称始终是“Max”,所以我不能使用Replace("Old_Value", "New_Value"); 所以我需要找到标题 {Verdieping 1} 然后查找“Max”并写下值直到它到达 "]);" 所以我最终得到了这样的结果:

Verdieping_1[0] = 15
Verdieping_1[1] = 20
Verdieping_1[0] = 10

Verdieping_2[0] = 25
Verdieping_2[1] = 10
Verdieping_2[2] = 40
Verdieping_2[3] = 20

然后,当我更改这些值时,我需要将它们写回到正确位置的文件中。现在我正在使用这段代码来读取并最终写入新文件:

var Model = System.IO.File.ReadAllText(@"C:\Base_Model.txt");

//format code here...

System.IO.File.WriteAllText(@"C:\New_Model.txt", Model);

有人能给我一些提示或帮助,告诉我如何最好地解决这个问题吗?

编辑 这是我要编辑的文件的实际文件结构:

{Atom: Verdieping 2}

int015(0, 64, [ 
1
2
3
]);
int015(1, 64, [`ActivityID`
20
21
33
]);
int015(2, 64, [`vtp`
139830296
189540320
169919424
]);
int015(3, 64, [`%`
100
100
100
]);
int015(4, 64, [`Max`
15
5
20
]);
int015(5, 64, [`Fill (1 = fill, 0 = empty)`
1
1
0
]);
SetStatus(0);
int018;


{Atom: Verdieping 2}

int015(0, 64, [ 
1
2
3
]);
int015(1, 64, [`ActivityID`
22
23
24
]);
int015(2, 64, [`vtp`
166058172
165557860
155960564
]);
int015(3, 64, [`%`
100
100
100
]);
int015(4, 64, [`Max`
15
20
10
]);
int015(5, 64, [`Fill (1 = fill, 0 = empty)`
0
1
1
]);
SetStatus(0);
int018;

我之前所说的“Max”实际上被称为: int015(4, 64, [Max

正如您所见,每一层的名称都是相同的,但变量的数量是不同的。

感谢到目前为止的帮助!

【问题讨论】:

  • "一些想法???"听起来像解析器。
  • 听起来你应该使用 Xml 而不是文本文件
  • 应该有一些代码来生成这个文本文件。它的算法/逻辑是什么?
  • @L.B 将regexp 帮助 OP 吗?
  • @bonCodigo 可能,但跳过的部分 (A bunch of data) 可能会给我们文本文件的结构。如果不了解整个结构,所有答案都会是蹩脚的。

标签: c# wpf replace


【解决方案1】:
var result = Regex.Matches(File.ReadAllText(fileName), @"\[`Max`(.*?)\]", RegexOptions.Singleline)
            .Cast<Match>()
            .Select(m => m.Groups[1].Value.Split(" \t\n\r".ToArray(), StringSplitOptions.RemoveEmptyEntries))
            .ToList();

foreach (var v in result)
{
    Console.WriteLine(String.Join(", ", v));
}

输出:

15, 5, 20
15, 20, 10

【讨论】:

    【解决方案2】:

    也许是正则表达式?我做了这个快速的回答,但是不应该复制粘贴;你可以考虑一下结果。

    在这个答案中,我希望您的数组按时间顺序排列,以防止源代码太长和混乱。

    我为“DataContainer”对象读取的文件看起来与下面的文件相同:

    {Verdieping 1}
    
    A bunch of data
    
    'Max'
    15
    20
    10
    ]);
    
    More data
    
    {Verdieping 2}
    
    A bunch of data
    
    'Max'
    25
    10
    40
    20
    ]);
    

    首先我在字符串中找到每个 'Max' 然后我把下面的所有数据都打印出来

    用于查找此内容的正则表达式是:\'Max\'.*?\]\);

    试试这段代码看看结果

    // fill our container
                string DataContainer = string.Empty;
                using (StreamReader sr = new StreamReader(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestFile.txt"))) {
                    DataContainer = sr.ReadToEnd();
                }
    
                // print data
                Match regMatch = Regex.Match(DataContainer, @"\'Max\'.*?\]\);", RegexOptions.Singleline);
                int verdiepc = 0;
                while (regMatch.Success) {
                    string[] Data = regMatch.Value.Replace("\r", "").Split('\n');
    
                    for (int I = 1; I < Data.Length - 1; I++) {
                        Console.WriteLine("Verdieping_{0}[{1}] = {2}"
                            , verdiepc, I, Data[I]);
                    }
                    Console.Write("\n");
    
                    verdiepc ++;
                    regMatch = regMatch.NextMatch();
                }
    
                // prevent immidiate exit
                Console.ReadKey();
    

    输出将是:

    Verdieping_0[1] = 15
    Verdieping_0[2] = 20
    Verdieping_0[3] = 10
    
    Verdieping_1[1] = 25
    Verdieping_2[2] = 10
    ........ etc..
    

    我希望你可以使用这个答案。这是一个关于如何使用 Regex 解析文件的草图

    【讨论】:

      【解决方案3】:
              string LoadedFile = File.ReadAllText(@"C:\Base_Model.txt");
              StringBuilder result = new StringBuilder();
              for (int i = 1; i < Int32.MaxValue; i++)
              {
                  Match ma = Regex.Match(LoadedFile, "Verdieping " + i.ToString() + ".+?'Max'.*?([0-9].+?)[]][)];", RegexOptions.Singleline);
                  if(!ma.Success)
                  {
                      break;
                  }
                  string a = ma.Result("$1");
                  MatchCollection mc = Regex.Matches(a, "(\\d+?)\r\n", RegexOptions.Singleline);
      
                  for (int j = 0; j < mc.Count; j++)
                  {
                      result.AppendLine(String.Format("Verdieping_{0}[{1}] = {2}", i, j, mc[j].Result("$1")));
                  }
                  result.AppendLine(String.Empty);
              }
      
              File.WriteAllText(@"C:\New_Model.txt", result.ToString());
      

      【讨论】:

        【解决方案4】:

        您可以初始化一个新的 List 或 string,它将包含所需的输出。然后,读取文件获取目标部分之间的信息,并将[ 和]); 之间的值插入到string 的List 中。

        示例

        static List<string> ReadFile(string Path, string Section)
        {
            #region Declare Variables
            string[] Lines = File.ReadAllLines(Path); //Read Path into Lines
            int CurrentValue = 1; //Declare CurrentValue as an Integer of value 1
            List<string> RequiredValues = new List<string>(); //Initialize a new List of string of name RequiredValues
            #endregion
            #region Collect Information
            //Look through the section getting the data between [ and ]);
            for (int i = 0; i < Lines.Length; i++)
            {
                if (Lines[i].StartsWith("{" + Section + "}"))
                {
                    i++;
                    while (!Lines[i].StartsWith("{") && !Lines[i].EndsWith("}"))
                    {
                        i++;
                        if (Lines.Length > i)
                        {
                            if (Lines[i].Contains('['))
                            {
                                while (true)
                                {
        
                                    i++;
                                    if (Lines[i].Contains("]);"))
                                    {
                                        break;
                                    }
                                    RequiredValues.Add(Section + "[" + CurrentValue.ToString() + "] = " + Lines[i]);
                                    CurrentValue++;
                                }
                            }
                            RequiredValues.Add("");
                        }
                        else
                        {
                            break; //Reached the end of the document
                        }
                    }
                }
            }
            #endregion
            return RequiredValues; //Return RequiredValues
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            List<string> Contents = ReadFile(@"C:\Base_Model.txt", "Atom: Verdieping 2");
            foreach (string str in Contents)
            {
                System.Diagnostics.Debug.WriteLine(str); //Write str to the trace listeners
            }
        }
        

        示例输入

        {Atom: Verdieping 2}
        
        int015(0, 64, [ 
        4
        5
        6
        ]);
        int015(1, 64, [`ActivityID`
        20
        21
        33
        ]);
        int015(2, 64, [`vtp`
        139830296
        189540320
        169919424
        ]);
        int015(3, 64, [`%`
        100
        100
        100
        ]);
        int015(4, 64, [`Max`
        15
        5
        20
        ]);
        int015(5, 64, [`Fill (1 = fill, 0 = empty)`
        1
        1
        0
        ]);
        SetStatus(0);
        int018;
        
        {Atom: Verdieping 1}
        
        int015(0, 64, [ 
        1
        2
        3
        ]);
        int015(1, 64, [`ActivityID`
        22
        23
        24
        ]);
        int015(2, 64, [`vtp`
        166058172
        165557860
        155960564
        ]);
        int015(3, 64, [`%`
        100
        100
        100
        ]);
        int015(4, 64, [`Max`
        15
        20
        10
        ]);
        int015(5, 64, [`Fill (1 = fill, 0 = empty)`
        0
        1
        1
        ]);
        SetStatus(0);
        int018;
        

        样本输出

        阅读Atom: Verdieping 2返回以下内容

        Atom: Verdieping 2[1] = 4
        Atom: Verdieping 2[2] = 5
        Atom: Verdieping 2[3] = 6
        
        Atom: Verdieping 2[4] = 20
        Atom: Verdieping 2[5] = 21
        Atom: Verdieping 2[6] = 33
        
        Atom: Verdieping 2[7] = 139830296
        Atom: Verdieping 2[8] = 189540320
        Atom: Verdieping 2[9] = 169919424
        
        Atom: Verdieping 2[10] = 100
        Atom: Verdieping 2[11] = 100
        Atom: Verdieping 2[12] = 100
        
        Atom: Verdieping 2[13] = 15
        Atom: Verdieping 2[14] = 5
        Atom: Verdieping 2[15] = 20
        
        Atom: Verdieping 2[16] = 1
        Atom: Verdieping 2[17] = 1
        Atom: Verdieping 2[18] = 0
        

        读取Atom: Verdieping 1返回以下输出

        Atom: Verdieping 1[1] = 1
        Atom: Verdieping 1[2] = 2
        Atom: Verdieping 1[3] = 3
        
        Atom: Verdieping 1[4] = 22
        Atom: Verdieping 1[5] = 23
        Atom: Verdieping 1[6] = 24
        
        Atom: Verdieping 1[7] = 166058172
        Atom: Verdieping 1[8] = 165557860
        Atom: Verdieping 1[9] = 155960564
        
        Atom: Verdieping 1[10] = 100
        Atom: Verdieping 1[11] = 100
        Atom: Verdieping 1[12] = 100
        
        Atom: Verdieping 1[13] = 15
        Atom: Verdieping 1[14] = 20
        Atom: Verdieping 1[15] = 10
        
        Atom: Verdieping 1[16] = 0
        Atom: Verdieping 1[17] = 1
        Atom: Verdieping 1[18] = 1
        

        注意:使用此方法,即使您有两个同名的部分,应用程序也只会收集它遇到的第一个部分之间的信息。

        谢谢,
        希望对您有所帮助 :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-07
          • 2021-01-23
          • 2013-05-03
          • 2023-03-17
          • 2011-03-22
          • 1970-01-01
          • 2021-08-14
          • 1970-01-01
          相关资源
          最近更新 更多