【问题标题】:How to combine two function's for file deletion如何结合两个功能进行文件删除
【发布时间】:2014-12-21 20:25:07
【问题描述】:

我有两个不同的函数来处理两种不同类型的输入文本文件。一个带双引号的文本文件,一个不带双引号的文本文件。

我想知道如何将这两个函数组合成一个通用的单个函数,以便更有效地处理

代码:

//this the function to handle text file without double quotes
public void stack1()
    {
        string old;
        string iniPath = Application.StartupPath + "\\list.ini";
        bool isDeleteSectionFound = false;
        List<string> deleteCodeList = new List<string>();
        using (StreamReader sr = File.OpenText(iniPath))
        {
            while ((old = sr.ReadLine()) != null)
            {
                if (old.Trim().Equals("[DELETE]"))
                {
                    isDeleteSectionFound = true;
                }
                if (isDeleteSectionFound && !old.Trim().Equals("[DELETE]"))
                {
                    deleteCodeList.Add(old.Trim());
                }
            }
        }

        StringBuilder sb = new StringBuilder();
        using (StreamReader reader = File.OpenText(textBox1.Text))
        {
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();
                var value = line.Split('\t');
                bool deleteLine = value.Any(v => deleteCodeList.Any(w => v.Equals(w)));
                if (!deleteLine)
                {
                    sb.Append(line + Environment.NewLine);
                }
            }
        }
        File.WriteAllText(textBox1.Text, sb.ToString());
        //return;
    }

     //this the function to handle text file with double quotes
    public void stack()
    {
        string old;
        string iniPath = Application.StartupPath + "\\list.ini";
        bool isDeleteSectionFound = false;
        List<string> deleteCodeList = new List<string>();
        using (StreamReader sr = File.OpenText(iniPath))
        {
            while ((old = sr.ReadLine()) != null)
            {
                if (old.Trim().Equals("[DELETE]"))
                {
                    isDeleteSectionFound = true;
                }
                if (isDeleteSectionFound && !old.Trim().Equals("[DELETE]"))
                {
                    deleteCodeList.Add(old.Trim());
                }
            }
        }

        StringBuilder sb = new StringBuilder();
        using (StreamReader reader = File.OpenText(textBox1.Text))
        {
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();
                var values = line.Split('\t').Select(v => v.Trim(' ', '"'));
                bool deleteLines = values.Any(v => deleteCodeList.Any(w => v.Equals(w)));
                if (!deleteLines)
                {
                    sb.Append(line + Environment.NewLine);
                }
            }
        }
        File.WriteAllText(textBox1.Text, sb.ToString());
        MessageBox.Show("finish");

    }

【问题讨论】:

    标签: c# string text text-files csv


    【解决方案1】:

    这两个函数之间的唯一区别是这一行:

    // stack1 function
    var value = line.Split('\t');
    
    // stack2 function
    var values = line.Split('\t').Select(v => v.Trim(' ', '"'));
    

    最简单的方法可能是在你的方法中添加一个参数,然后在拆分后添加检查:

    public void Split(bool shouldTrimQuotes)
    {
         ...
    
         IEnumerable<string> value = line.Split('\t');         
         if (shouldTrimQuotes)
         {
             value = value.Select(v => v.Trim(' ', '"'));
         }
    
         ...
    }
    

    在一种情况下,您将传递 true 作为参数(这将导致引号被修剪),而在第二种情况下,您将传递 false 以表明您不想修剪它们:

    // split, but don't trim quotes before comparison
    Split(shouldTrimQuotes: false);
    
    // split, trim quotes before comparison
    Split(shouldTrimQuotes: true);
    

    您也可以尝试一下并尝试重构整个事物,尝试将较小的通用代码片段提取到单独的方法中,这可能会使它们在做什么更清楚。这是一种方法,例如:

    // rewrites the specified file, removing all lines matched by the predicate
    public static void RemoveLinesFromFile(string filename, Func<string, bool> match)
    {
        var linesToKeep = File.ReadAllLines(filename)
            .Where(line => match(line))
            .ToList();
    
        File.WriteAllLines(filename, linesToKeep);
    }
    
    // gets the list of "delete codes" from the specified ini file
    public IList<string> GetDeleteCodeList(string iniPath)
    {
        return File.ReadLines(iniPath)
            .SkipWhile(l => l.Trim() != "[DELETE]")
            .Skip(1).ToList();
    }
    
    // removes lines from a tab-delimited file, where the specified listOfCodes contains
    // at least one of the tokens inside that line
    public static void RemoveLinesUsingCodeList(
        string filename,
        IList<string> listOfCodes,
        bool shouldTrimQuotes)
    {
        RemoveLinesFromFile(filename, line =>
        {
            IEnumerable<string> tokens = line.Split('\t');               
            if (shouldTrimQuotes)
            {
                tokens = tokens.Select(v => v.Trim(' ', '"'));
            }
            return (tokens.Any(t => listOfCodes.Any(t.Equals)));
        });
    }
    

    【讨论】:

    • 我认为不需要参数。双引号不是文件名中的有效符号。您可以随时调整您的输入。
    • @Neolisk:我不认为这些值是必要的文件名。 OP 正在解析一个制表符分隔的文件,但在某些情况下只想修剪引号。
    • @Groo 你能告诉我如何添加参数吗?我对此真的很陌生..我也收到一个错误Cannot implicitly convert type 'System.Collections.Generic.IEnumerable&lt;string&gt;' to 'string[]'. An explicit conversion exists (are you missing a cast? in the line value = value.Select(v => v.Trim(' ', '"'));`
    • @stacy: 是的,对不起,value 变量的类型应该显式设置为IEnumerable&lt;string&gt;,否则编译器将使用string[],因为var 关键字。
    • @stacy:删除这些方法中的第一个,并修改第二个以具有输入参数和if 子句。您最终会得到一个根据其输入参数表现不同的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    相关资源
    最近更新 更多