【问题标题】:C# - Replace text mid-string and keep the rest of the string, duplicate linesC# - 替换字符串中间的文本并保留字符串的其余部分,重复行
【发布时间】:2011-09-26 06:31:33
【问题描述】:

我有两个 .txt 文档,我想在其中一个文件中搜索第二个文件中的密钥。如果找到键,我想用第二个文件中键后面的文本替换匹配项。另外,我想根据文件中的数字添加“T”或“B”。

这是第一个文件的示例:

   1       0010    SOMETEXT/NUMBERS    SOME TEXT, TEXT
   .2      0020    SOMETEXT/NUMBERS    SOME TEXT, TEXT, TEXT
   1       0020A   SOMETEXT/NUMBERS    SOME TEXT,TEXT
   .1      2000    SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT
   ..3     9123A   SOMETEXT/NUMBERS    SOME TEXT
   ...     ...     ...                 ...

这是第二个文件的示例:

  0010    ABCD EFG
  0020    C01
  0020A   C02, C3, C004, C9901, C938, C12
  2000    R123, R13, D34 
  9123A   SOMETEXT
  ...     ...

从这两个文件中,我想使用第二个文件中的“键”(在每个新行的开头)。所以在这个例子中,键是:0010、0020、0020A、2000、9123A。获得密钥后,我想搜索第二列中的第一个文本文档以查看是否有匹配项。如果有匹配项(在这种情况下它们都匹配),我想替换第一个文档中的文本并使用更新的文本创建一个新文档。另外,如果第二个文件中的键后面有多个值,我想将这些行复制下来。请看下面,看看我的意思。

新文档如下所示:

   1       ABCD EFG   SOMETEXT/NUMBERS    SOMETEXT, TEXT
   .2      C01        SOMETEXT/NUMBERS    SOME TEXT, TEXT, TEXT
   1       C02        SOMETEXT/NUMBERS    SOME TEXT,TEXT             //--------------------
   1       C3         SOMETEXT/NUMBERS    SOME TEXT,TEXT             // Copied the lines
   1       C004       SOMETEXT/NUMBERS    SOME TEXT,TEXT             // down if there are
   1       C9901      SOMETEXT/NUMBERS    SOME TEXT,TEXT             // multiple values in
   1       C938       SOMETEXT/NUMBERS    SOME TEXT,TEXT             // document 2.
   1       C12        SOMETEXT/NUMBERS    SOMETEXT,TEXT              //--------------------
   .1      R123       SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT       //--------------
   .1      R13        SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT       // COPIED ALSO
   .1      D34        SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT       //--------------
   ..3     SOMETEXT   SOMETEXT/NUMBERS    SOME TEXT
   ...     ...     ...                 ...

另外,如果键以“A”结尾,我想在上面的字符串末尾添加一个“T”。如果键不以“A”结尾,我想在上面的字符串末尾添加一个“B”。

几行示例:

   .1      R123       SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT         B       //key was 2000
   .1      R13        SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT         B       //key was 2000
   .1      D34        SOMETEXT/NUMBERS    SOME TEXT,TEXT, TEXT         B       //key was 2000
   ..3     SOMETEXT   SOMETEXT/NUMBERS    SOME TEXT                    T       //key was 9123A


问题:

  • 如何在一个文件中搜索第二个文件中的密钥?
    • 找到后,如何将第一个文本中的项目替换为第二个文本中的项目?
  • 替换文件后,是否必须重新连接字符串?
  • 在每行正确后,是否有“最佳”方式在每行末尾添加“T”或“B”(这取决于键是否有“A”)?
  • 对此还有其他建议吗?

这是我一直在尝试使用的一些代码。但是我无法按我的意愿得到它,而且代码也没有按我的预期工作。:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Collections;

namespace BOM_Formatter
{
  public partial class bomForm : Form
  {
    // Create OpenFileDialogs to request paths and file names to open.
    OpenFileDialog openFile = new OpenFileDialog();
    OpenFileDialog openRefs = new OpenFileDialog();

    // Create a SaveFileDialog to request a path and file name to save.
    SaveFileDialog saveFile = new SaveFileDialog();

    string filePath = "C:\\Users\\FileText.txt";
    string refsPath = "C:\\Users\\RefsText.txt";

    public bomForm()
    {
        InitializeComponent();
    }

    //*********************************************************
    //******************* OPEN FILE BUTTON ********************
    //*********************************************************
    private void openButton_Click(object sender, EventArgs e)
    {
        // Initialize the OpenFileDialog to specify the .txt extension.
        openFile.DefaultExt = "*.txt";
        openFile.Filter = ".txt Files|*.txt";
        openFile.RestoreDirectory = true;

        try
        {
            // Open the contents of the file into the originalTextRichTextBox.
            if (openFile.ShowDialog() == DialogResult.OK && openFile.FileName.Length > 0)
                originalTextRichTextBox.LoadFile(openFile.FileName, RichTextBoxStreamType.PlainText);

            // Throws a FileNotFoundException otherwise.
            else
                throw new FileNotFoundException();

            // Calls to format the opened file.
            openFileFormatHelper();

            formattedTextRichTextBox.SaveFile(filePath, RichTextBoxStreamType.PlainText);
        }

        // Catches an exception if the file was not opened.
        catch (Exception)
        {
            MessageBox.Show("There was not a specified file path.", "Path Not Found Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    //*********************************************************
    //******************** OPEN REFS BUTTON *******************
    //*********************************************************
    private void openRefsButton_Click(object sender, EventArgs e)
    {
        // Initialize the OpenFileDialog to specify the .txt extension.
        openRefs.DefaultExt = "*.txt";
        openRefs.Filter = ".txt Files|*.txt";
        openRefs.RestoreDirectory = true;

        try
        {
            // Open the contents of the file into the originalTextRichTextBox.
            if (openRefs.ShowDialog() == DialogResult.OK && openRefs.FileName.Length > 0)
                refsTextRichTextBox.LoadFile(openRefs.FileName, RichTextBoxStreamType.PlainText);

            // Throws a FileNotFoundException otherwise.
            else
                throw new FileNotFoundException();

            // Calls to format the opened refs file.
            openRefsFormatHelper();

            formattedRefsTextRichTextBox.SaveFile(refsPath, RichTextBoxStreamType.PlainText);
        }

        // Catches an exception if the file was not opened.
        catch (Exception)
        {
            MessageBox.Show("There was not a specified file path.", "Path Not Found Error",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    //*********************************************************
    //******************* SAVE FILE BUTTON ********************
    //*********************************************************
    private void saveButton_Click(object sender, EventArgs e)
    {
        // Initialize the SaveFileDialog to specify the .txt extension for the file.
        saveFile.DefaultExt = "*.txt";
        saveFile.Filter = ".txt Files|*.txt";
        saveFile.RestoreDirectory = true;

        try
        {
            // Save the contents of the formattedTextRichTextBox into the file.
            if (saveFile.ShowDialog() == DialogResult.OK && saveFile.FileName.Length > 0)
                finalTextRichTextBox.SaveFile(saveFile.FileName, RichTextBoxStreamType.PlainText);

            // Throws a FileNotFoundException otherwise.
            else
                throw new FileNotFoundException();
        }

        // Catches an exception if the file was not saved.
        catch (Exception)
        {
            MessageBox.Show("There was not a specified file path.", "Path Not Found Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    //*********************************************************
    //******************* CLEAR FILE BUTTON *******************
    //*********************************************************
    private void clearButton_Click(object sender, EventArgs e)
    {
        try
        {
            // Resets the text in all of the boxes.
            originalTextRichTextBox.ResetText();
            formattedTextRichTextBox.ResetText();
            refsTextRichTextBox.ResetText();
            formattedRefsTextRichTextBox.ResetText();
            finalTextRichTextBox.ResetText();
        }

        // Catches an exception if the either text box could not be cleared.
        catch (Exception)
        {
            MessageBox.Show("Could not clear the text.", "Clearing Text Box Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    //*********************************************************
    //******************* FORMAT FILE BUTTON ******************
    //*********************************************************
    private void formatButton_Click(object sender, EventArgs e)
    {
        try
        {
           //var list = new List<string>();
            openFileFormatHelper();
            openRefsFormatHelper();
           // formatAllHelper();

            finalFormatHelper();
        }

        // Catches an exception if the file was not opened.
        catch (Exception)
        {
            MessageBox.Show("Could not format text.", "Text Formatting Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    private void finalFormatHelper()
    {
        try
        {
            string[] openFileFinal = File.ReadAllLines(filePath);
            string[] openRefsFinal = File.ReadAllLines(refsPath);

            var result = new List<string>();
            string theOutput;
           // StringBuilder finalOutput = new StringBuilder();

            foreach (var fileLines in openFileFinal)
            {
                //Match numberStartMatch = Regex.Match(fileLines, @"^[\d]+");//[\s+[\d\w]+]*");
                var fileParts = fileLines.Split(' ');

                foreach (var refLines in openRefsFinal)
                {
                    var refsParts = refLines.Split(' ');
                    theOutput = fileParts.ToString();

                    if (fileParts[1].Equals(refsParts[0]))
                    {
                        theOutput = fileParts[0] + "\t" + fileParts[1].Replace(fileParts[1], refsParts[1]) 
                            + "\t" + fileParts[2] + "\t" + fileParts[3] + "\t" + fileParts[4];
                        result.Add(string.Join(" ", theOutput));
                    }
                    else
                        result.Add(theOutput);
                }
               // finalTextRichTextBox.AppendText(result.ToString());
                // Otherwise keep the line how it is.
            }
            foreach (var line in result)
            {
                finalTextRichTextBox.AppendText(line + "\n");
            }
        }

        // Catches an exception if the file could not be formatted.
        catch (Exception)
        {
            MessageBox.Show("There was a problem formatting the 'Final File'.", "Final File Format Error",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }


    //*********************************************************
    //******************* OPEN FILE HELPER ********************
    //*********************************************************
    private void openFileFormatHelper()
    {
        try
        {
            // Resets the formattedTextRichTextBox so multiple files aren't loaded on top of eachother.
            formattedTextRichTextBox.ResetText();

            foreach (string line in File.ReadAllLines(openFile.FileName))
            {
                // Uses regular expressions to find a line that has, digit(s), space(s), digit(s) + letter(s),
                // space(s), digit(s), space(s), any character (up to 25 times).
                Match theMatch = Regex.Match(line, @"^[\.*\d]+\s+[\d\w]+\s+[\d\-\w*]+\s+.{25}");

                if (theMatch.Success)
                {
                    // Stores the matched value in string output.
                    string output = theMatch.Value;

                    // Replaces tabs and extra space with only 1 space delimiter
                    output = Regex.Replace(output, @"\s+", " ");

                    // Sets the formattedTextRichTextBox to the string output.
                    formattedTextRichTextBox.AppendText(output);
                    formattedTextRichTextBox.AppendText("\n");
                }
            }
        }

        // Catches an exception if the file was not opened.
        catch (Exception)
        {
            MessageBox.Show("There was a problem formatting the 'Open File'.", "Open File Format Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        // Creates a final string of the formatted rich text box.
        //string openFileFinal = formattedTextRichTextBox.Text.ToString();
    }

    //*********************************************************
    //******************* OPEN REFS HELPER ********************
    //*********************************************************
    private void openRefsFormatHelper()
    {
        try
        {
            formattedRefsTextRichTextBox.ResetText();
            // Reads the lines in the file to format.
            var reader = File.OpenText(openRefs.FileName);

            // Creates a list for the lines to be stored in.
            var list = new List<string>();

            // Adds each line in the file to the list.
            while (true)
            {
                var line = reader.ReadLine();
                if (line == null) 
                    break;
                list.Add(line);
            }

            // Handles all of the requirements for the reference text.
            list = fourDigitRequirement(list);
            list = concatRequirement(list);
            list = startsWithBRequirement(list);
            list = elementIsBRequirement(list);
            list = removeTRequirement(list);

            // Prints the formatted refs to the richtextbox.
            foreach (var line in list)
                formattedRefsTextRichTextBox.AppendText(line + "\n");

            // Creates a final string of the formatted refs rich text box.
          //string refsFileFinal = formattedRefsTextRichTextBox.Text.ToString();
        }

        // Catches an exception if the file could not be formatted.
        catch (Exception)
        {
            MessageBox.Show("There was a problem formatting the 'Refs File'.", "Refs File Format Error",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    //*********************************************************
    //****************** FORMAT ALL HELPER ********************
    //*********************************************************
   /* private void formatAllHelper()
    {
        try
        {
            finalTextRichTextBox.ResetText();

            // Reads the lines in the file to format.
            var fileReader = File.OpenText(formattedTextRichTextBox.Text);
            var refsReader = File.OpenText(formattedRefsTextRichTextBox.Text);

            // Creates a list for the lines to be stored in.
            var list = new List<string>();
            var list2 = new List<string>();

            // Adds each line in the file to the list.
            while (true)
            {
                var line = fileReader.ReadLine();
                var line2 = refsReader.ReadLine();
                if (line == null)
                    break;
                if (line2 == null)
                    break;

                list.Add(line);
                list2.Add(line2);
            }

            list = finalTextRequirement(list, list2);

            // Prints the formatted refs to the richtextbox.
            foreach (var line in list)
                finalTextRichTextBox.AppendText(line + "\n");
        }

        // Catches an exception if the file could not be formatted.
        catch (Exception)
        {
            MessageBox.Show("There was a problem formatting the 'Final Text' file.", "Final File Format Error",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

    public List<string> finalTextRequirement(List<string> list, List<string> list2)
    {
        // Creates variables of the text in the two rich text boxes.
        var openFileFinal = File.ReadAllLines(formattedTextRichTextBox.Text);
        var openRefsFinal = File.ReadAllLines(formattedRefsTextRichTextBox.Text);
        StringBuilder finalOutput = new StringBuilder();
        var result = new List<string>();

        try
        {
            finalTextRichTextBox.ResetText();

            // Splits the text
            var openFileFinalLines = openFileFinal.Select(f => f.Split(' ')).ToDictionary(g => g[1], h => h);
            var openRefsFinalLines = openRefsFinal.Select(f => f.Split(' ')).ToDictionary(g => g[0], h => h[1].Split(','));

            foreach (var line in openFileFinalLines)
            {
                if (openRefsFinalLines.ContainsKey(line.Key))
                    finalOutput.Append(Combine(line.Value, openRefsFinalLines[line.Key]));

                else
                    finalOutput.AppendLine(string.Join("\t", line.Value));
            }
        }

        // Catches an exception if the final output could not be created.
        catch (Exception)
        {
            MessageBox.Show("There was a problem creating the final document.", "Final Text Formatting Error",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        finalTextRichTextBox.Text = finalOutput.ToString();
        return result;
        /*
        // Creates a new list to return with new format.
        var result = new List<string>();
        var openFileFinal = File.ReadAllLines(formattedTextRichTextBox.Text);

        foreach (var line in openFileFinalLines)
        {
            if (openRefsFinalLines.ContainsKey(line.Key))
                finalOutput.Append(Combine(line.Value, openRefsFinalLines[line.Key]));

            else
                finalOutput.AppendLine(string.Join("\t", line.Value));
        }
    }

    string Combine(string[] openFileFinalLines, string[] openRefsFinalLines)
    {
        StringBuilder aBuilder = new StringBuilder();

        foreach (var theString in openRefsFinalLines)
        {
            aBuilder.AppendLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}", openFileFinalLines[0], theString, openFileFinalLines[2],
                openFileFinalLines[3], openFileFinalLines[1].EndsWith("A") ? "T" : "B"));
        }

        return aBuilder.ToString();
    }*/

    //*************************************************************
    //***************** ELEMENT IS B REQUIREMENT ******************
    //*************************************************************
    // This handles the requirement of the second element in the list being a "B".
    static List<string> elementIsBRequirement(List<string> list)
    {
        // Creates a new list to return with new format.
        var result = new List<string>();

        // Checks each line in the list.
        foreach (var line in list)
        {
            // Splits each line into 'parts'
            var parts = line.Split(' ');

            // Checks if the second 'part' array is "B"
            if (parts[1].Equals("B"))
            {
                // If it is "B", replace with "A" and add to the new list "result"
                parts[0] += "A";
                parts[1] = string.Empty;

                result.Add(string.Join(" ", parts));
            }

            // Otherwise keep the line how it is.
            else
                result.Add(line);
        }

        // Returns the new list so it can be formatted further.
        return result;
    }

    //*************************************************************
    //***************** STARTS WITH B REQUIREMENT *****************
    //*************************************************************
    // This handles the requirement of the element starting with a "B".
    static List<string> startsWithBRequirement(List<string> list)
    {
        // Creates a new list to return with new format.
        var result = new List<string>();
        var i = 0;

        // Checks if the line begins with "B"
        foreach (var line in list)
        {
            // Splits each line into 'parts'
            var parts = line.Split(' ');

            // Checks if the first 'part' array is "B"
            if (parts[0].Equals("B"))
            {
                // If it is "B", copy the previous line down and add "A" where "B" was at
                // and add to the new list "result"
                parts[0] = string.Empty;
                result.Add(list[i - 1].Split(' ')[0] + "A" + string.Join(" ", parts));
            }

            // Otherwise keep the line how it is.
            else
                result.Add(line);

            i++;
        }

        // Returns the new list so it can be formatted further.
        return result;
    }

    //*************************************************************
    //****************** CONCAT LIST REQUIREMENT ******************
    //*************************************************************
    // This handles the requirement of concatting the list.
    static List<string> concatRequirement(List<string> list)
    {
        // Creates a new list to return with new format.
        var result = new List<string>();

        // Checks each line in the list.
        foreach (var line in list)
        {
            // Splits each line into 'parts'
            var parts = line.Split(' ');
            int test;

            // Concats everything together
            if (int.TryParse(parts[0], out test) || parts[0].Equals("B"))
                result.Add(line);

            // Otherwise result - 1
            else
                result[result.Count - 1] += line;
        }

        // Returns the new list so it can be formatted further.
        return result;
    }

    //*************************************************************
    //***************** REMOVE THE T REQUIREMENT ******************
    //*************************************************************
    // This handles the requirement of removing the "T".
    static List<string> removeTRequirement(List<string> list)
    {
        // Creates a new list to return with new format.
        var result = new List<string>();

        // Checks each line in the list.
        foreach (var line in list)
        {
            // Splits each line into 'parts'
            var parts = line.Split(' ');

            // Checks if the second 'part' array is "T", if it is, remove "T"
            if (parts[1].Equals("T"))
                parts[1] = string.Empty;

            // Add the new string to the result.
            result.Add(string.Join(" ", parts).Replace("  ", " "));
        }

        // Returns the new list so it can be formatted further.
        return result;
    }

    //*************************************************************
    //****************** FOUR DIGITS REQUIREMENT ******************
    //*************************************************************
    // This handles the requirement of the digits being a certain length.
    static List<string> fourDigitRequirement(List<string> list)
    {
        // Creates a new list to return with new format.
        var result = new List<string>();

        // Checks each line in the list.
        foreach (var line in list)
        {
            // Splits each line into 'parts'
            var parts = line.Split(' ');
            int test;

            // Checks if the array[0] (digits) is the proper length.
            if (int.TryParse(parts[0], out test))
            {
                // If it is not a length of 4 digits, add "O" to the front until it is.
                parts[0] = parts[0].PadLeft(4, '0');

                // Add the new string to the result list.
                result.Add(string.Join(" ", parts));
            }

            // Otherwise keep the line how it is.
            else
                result.Add(line);
        }

        // Returns the new list so it can be formatted further.
        return result;
    }
  }
}

现在我必须将两个文本框保存到一个 .txt 文件中,然后才能将它们“上传”到最终格式按钮中以完全格式化和合并文件。无论如何不必将文件保存为硬拷贝,而是从 formattedTextRichTextBox 和 formattedRefsRichTextBox 上传它们以进行更多格式化?

【问题讨论】:

  • 列是否用制表符分隔?还是空格?
  • 第一个文件的标签,第二个文件的空格
  • 但是,我可以添加: output = Regex.Replace(input, @"\s+", " ");使它们都在空间中。
  • 其实我觉得转换成tab会更方便

标签: c# string text replace duplicates


【解决方案1】:

我会读入这两个文件(可能使用 File.ReadAllLines())。这将为您提供一个包含文件中所有行的数组。从那里,我将使用 LINQ Select 方法将行投影为键值对(或类似的东西),也许转换 ToDictionary()。然后在内存中执行所有花哨的连接和逻辑并将其写回一个新文件。即将发布的代码(可能)

编辑:我认为这会产生您正在寻找的输出。

string FileMerger()
{
    var file1 = File.ReadAllLines(@"c:\....\File1.txt");
    var file2 = File.ReadAllLines(@"c:\....\File2.txt");

    var file1Lines = file1.Select(f => f.Split('\t')).ToDictionary(f => f[1], f => f);
    var file2Lines = file2.Select(f => f.Split('\t')).ToDictionary(f => f[0], f => f[1].Split(','));

    StringBuilder newOutput = new StringBuilder();

    foreach(var line in file1Lines) 
    {
        if(file2Lines.ContainsKey(line.Key)) 
        {
            newOutput.Append(Combine(line.Value, file2Lines[line.Key]));
        }
        else 
        {
            newOutput.AppendLine(string.Join("\t", line.Value));
        }
    }

    return newOutput.ToString();
}

string Combine(string[] file1Line, string[] file2Line)
{
    StringBuilder builder = new StringBuilder();

    foreach(var str in file2Line)
    {
        builder.AppendLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}", file1Line[0], str, file1Line[2], file1Line[3], file1Line[1].EndsWith("A") ? "T" : "B"));
    }

    return builder.ToString();
}

【讨论】:

  • 在你设置file1Lines & file2Lines的那一行,“Select”后面的所有内容是什么意思?另外,我在我的代码中输入了这个,MS Visual Studio 2010 无法识别来自“Select(f => f.Split...);”的 f.Split文字
  • Select 语句获取数组中的每个元素并对其应用一些变换(“投影”)。所以 file1Lines 等于 file1 中的每一行在制表符上拆分,然后转换为字典,其中字典的键是数组的第二个元素(索引 1),值是整行(作为在制表符上拆分的数组)..... 至于你得到的 f.Split(..) 的错误,你能粘贴你得到的错误吗?它是字符串类的实例方法。
  • 太酷了。感谢您的解释!它只是说:“char”不包含“Split”的定义,并且找不到接受第一个参数类型“char”的扩展方法“Split”(您是否缺少使用指令或程序集引用?)
  • 我发现了错误..我错过了“File.ReadAllLines”..哎呀
  • 但是,现在 MSVS2010 无法识别“.ToDictionary”中的多个 f 和 Split(',')
【解决方案2】:

您想使用FileHelpers 库来读取文件,该文件会将文件读入对象。然后你可以使用 Linq 合并两个结果并生成新文件。

【讨论】:

    猜你喜欢
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 2016-01-08
    • 1970-01-01
    相关资源
    最近更新 更多