使用字符串生成器查找richtextbox中缺少的项目

时间:2015-03-08 14:35:36

标签: c# winforms

大家好我正在尝试使用某种匹配系统寻找丢失的物品。我的想法是根据需要填充我的richtextbox和格式 但是我想去一个目录并查找richtextbox中的项目,但是不在目录c:\ s \ slimyyyy中,到目前为止我正在使用字符串构建器,只有当列表中的第一项不是在目录但但如果第二个或第三个等等它将得到任何想法没有错误消息?到目前为止这是我的代码只有当richtextbox中的项目列表中的第一项时才有效。我希望能够只在按钮单击事件处理程序确定缺少的项目不在上述目录中,查找下面是我的代码到目前为止我做错了什么?提前感谢任何指导。

public void OutputErrorMessage(string messages)
{
    MessageBox.Show(messages, "You are missing files");
}

private void button4_Click(object sender, EventArgs e)
{
    string str = rchTxtContent.Text;
    var printList = new List<string>();
    string dir = @"C:\slim\slimyyyy";

    if (Directory.Exists(dir))
    {
        string[] pdf_specFiles = Directory.GetFiles(dir);
        if (pdf_specFiles.Length > 0)
        {
            // Declare  and instantiate new string builder
            StringBuilder builder = new StringBuilder();
            // The flag
            bool itemFound = false;

            // foreach (object item in listBox1.Items)
            foreach (object line in rchTxtContent.Lines)
            {
                foreach (string file in pdf_specFiles)
                {
                    string fileName = Path.GetFileName(file);
                    if (fileName == line.ToString())
                    {
                        itemFound = true;
                        printList.Add(Path.GetFullPath(file));
                    }
                }

                // Add the item to the list of missing items.
                if (!itemFound )
                {
                    // Append to the builder
                    // if (builder.Length == 0)
                    {
                        builder.AppendLine("[Missing Files]");
                    }
                    builder.AppendLine(line.ToString());
                }

2 个答案:

答案 0 :(得分:0)

如果您只想了解RichTextBox中的文件名与目录中的文件之间的区别,我认为您可以用更短的方式完成:

string directoryPath = @"C:\slim\slimyyyy";
if (!Directory.Exists(directoryPath))
    return; // error message or exception

List<string> filesInRichTextBox = richTextBox1.Lines.ToList();
List<string> filesInDirectory = Directory.GetFiles(directoryPath).Select(file => new FileInfo(file).Name).ToList(); // get all files (as strings) and just the filename of it (without the whole path)

List<string> result = filesInRichTextBox.Except(filesInDirectory).ToList(); // give me all the files in the RichTextBox that are not in the directory
string missingFiles = string.Format("Missing Files: {0}", string.Join(", ", result)); // which will be something like "Missing Files: abc.txt, def.txt, etc...

希望这有帮助!

答案 1 :(得分:0)

首先,如果您保持方法简单,您会发现代码更容易编写和维护。理想情况下,单个方法应该完成一件事。在您的示例中,您有一个方法可以执行以下操作:

  • 从目录中获取文件
  • 从文本框中获取名称列表
  • 比较列表,生成新列表

看来这是你需要最多帮助的最后一部分,所以让我们关注它。你要做的是归结为从一个字符串列表(从文本框开始)开始,并排除另一个字符串列表中的所有成员(目录中的文件名)。 在.NET中很容易做到:

List<string> GetMissingFiles(
    IEnumerable<string> desiredFiles, IEnumerable<string> actualFiles)
{
    return desiredFiles.Except(
        actualFiles.Select(file => Path.GetFileName(file))).ToList();
}

请注意,即使上述方法基本上只是一个语句,方法名称本身也可以通过描述操作来帮助记录调用代码。这有助于提高可读性,当然,封装在方法中的逻辑允许重用。

然后你可以像这样编写原始方法(仍然做了几件事,但更简单):

string dir = @"C:\slim\slimyyyy";

if (Directory.Exists(dir))
{
    string[] pdf_specFiles = Directory.GetFiles(dir);
    if (pdf_specFiles.Length > 0)
    {
        List<string> printList = GetMissingFiles(rchTextContent.Lines, pdf_specFiles);

        // do something with printList
    }
}

从您的示例中不清楚,当目录不存在或没有文件时,您是否真的要保持printList为空。逻辑似乎表明你想要一个丢失文件的列表(因此我使用的方法名称),但如果你在目录丢失或空的时候跳过构建列表,那么你最终得到一个空的文件列表,即使他们所有都不见了。

上述替代方案可能是:

string dir = @"C:\slim\slimyyyy";
IEnumerable<string> pdf_specFiles = Directory.Exists(dir) ?
    Directory.GetFiles(dir) : Enumerable.Empty<string>();

List<string> printList = GetMissingFiles(rchTextContent.Lines, pdf_specFiles);

// do something with printList

在该示例中,它始终从所需的文件列表中排除目录中的文件列表。如果缺少该目录,则使用空枚举,就像目录存在但是为空。这样,生成的printList对象将包含所有原始文件。

最后,我会注意到Windows文件系统都不区分大小写。如果字符串完全相同,包括大小写,则上述内容仅匹配。您可能更喜欢类似于文件系统使用的不区分大小写的比较。在这种情况下,只需将等式比较器传递给Except()方法:

List<string> GetMissingFiles(
    IEnumerable<string> desiredFiles, IEnumerable<string> actualFiles)
{
    return desiredFiles.Except(
        actualFiles.Select(file => Path.GetFileName(file)),
        StringComparer.OrdinalIgnoreCase).ToList();
}

如果你想要一个包含文本“[Missing Files]”的字符串,后面跟着每行的每个文件名,那也很简单:

string missingFilesText = "[Missing Files]" + Environment.NewLine +
    string.Join(Environment.NewLine, printList);


修改

因此,查看您的评论并再次查看原始代码,在我看来,您可以通过移动一行来获取您想要的代码:bool itemFound = false;

目前,该行代码位于foreach (object line in rchTxtContent.Lines)循环之外,这意味着itemFound标志在找到第一个项目后永远不会重置为false

如果你将那行代码移到里面 foreach (object line in rchTxtContent.Lines)循环,就在开头,我认为你会得到你想要的。

您发布的代码确实需要其他改进,恕我直言,您应该遵循我上面提供的建议。但是如果你关心的只是得到一些特定的输出,那么只需移动该变量的声明和初始化即可。