【问题标题】:looping for PDF files循环PDF文件
【发布时间】:2011-05-15 07:28:03
【问题描述】:

我的程序进入一个目录并搜索 pdf 文件来解析它们。这个程序一直在运行,所以我需要确保不要再次解析同一个文件。

我使用了一个列表来存储文件名,然后检查它们是否在其中。

我的代码在这方面不起作用,如果有人可以看看有什么问题,将不胜感激。

FileInfo[] filePaths = di.GetFiles("*.pdf");
for (int i = 0; i < filePaths.Length; i++)
{
    foreach (string fileName in usedFileNames)
    {
        if (fileName.Equals(filePaths[i].Name))
        {
            isInList = true;
        }
        else
        {
            isInList = false;
        }
    }
    if (isInList == false)
    {
        PDFReaderChooser chooser = new PDFReaderChooser(filePaths[i].Name);
        usedFileNames.Add(filePaths[i].Name);
    }

}

【问题讨论】:

  • 您的代码不起作用,因为您必须在 "isInList = true;" 之后插入一个 break 语句。
  • @AS-CII:这没有任何意义,因为他稍后会测试isInList == false;它有效地打破了那里......
  • 是的,但每次循环执行时,如果找到文件名,isInList 变量也会更新。示例:#1 - 相等,isInList = true; #2 - NotEqual, isInList = false。在这种情况下,变量假定的最后一个值是假的,因此结果是完全错误的。如果您不信任我,请自己测试代码:)另一种方法是删除 else 语句。
  • 我会用一个例子来备份 AS-CII。假设 filePaths 包含一个项目“first.pdf”,而 usedFileNames 包含两个项目“first.pdf”和“second.pdf”。现在让我们跟踪代码。
  • 你是完全正确的 AS-CII;我只是没有考虑下一次迭代。 else 远远超出了我通常会做的事情,以至于我只是掩饰了它;删除它的替代方法正是我习惯的。

标签: c# list file search


【解决方案1】:

试试这个:

FileInfo[] filePaths = di.GetFiles("*.pdf");
foreach(FileInfo fInfo in filePaths)
{
    if (!usedFileNames.Contains(fInfo.Name))
    {
        PDFReaderChooser chooser = new PDFReaderChooser(fInfo.Name);
        usedFileNames.Add(fInfo.Name);
    }
}

正如我对您的问题的评论,您发布的代码不起作用,因为您必须插入一个 break 语句,如下所示:

for (int i = 0; i < filePaths.Length; i++)
{
    bool isInList = false;

    foreach (string fileName in usedFileNames)
    {
        if (fileName.Equals(filePaths[i].Name))
            isInList = true;
    }

    if (isInList == false)
    {
        Console.WriteLine("Not in list! #{0}", x);
        usedFileNames.Add(filePaths[i].Name);
    }
}

无论如何,我建议您使用此问题回复中显示的技术之一。

【讨论】:

  • 好吧,我没有更改代码,因为也许他必须使用计数器。反正我修好了。谢谢:)
【解决方案2】:

虽然其他答案是解决问题的更好方法,但它们没有解释为什么原始代码不起作用。问题是该算法覆盖了 isInList 变量的值,因此这仅适用于列表中的最后一个文件。这将解决这个问题:

FileInfo[] filePaths = di.GetFiles("*.pdf"); 
for (int i = 0; i < filePaths.Length; i++) 
{ 
    isInList = false
    foreach (string fileName in usedFileNames) 
    { 
        if (fileName.Equals(filePaths[i].Name)) 
        { 
            isInList = true;
            break;
        } 
    } 
    if (isInList == false) 
    { 
        PDFReaderChooser chooser = new PDFReaderChooser(filePaths[i].Name); 
        usedFileNames.Add(filePaths[i].Name); 
    } 
} 

我要补充一点,对于您的 usedFileNames 集合,最好使用 HashSet 而不是 List。哈希集旨在有效地确定它是否包含给定项目。如果我没记错的话,该列表会进行线性搜索,这(对于大量项目)效率低下。

【讨论】:

  • +1 可以很好地解释原始问题,而特殊的隐形+1 可以提及HashSet;这不是我在自己的代码中做的事情,但我应该这样做!
【解决方案3】:

更简洁:

var fileNames = di.GetFiles("*.pdf")
                  .Select(f => f.Name)
                  .Where(n => !usedFileNames.Contains(n));
usedFileNames.AddRange(fileNames);

foreach (var fileName in fileNames)
{
    var chooser = new PDFReaderChooser(fileName);
}

这很好地从处理它们的逻辑(循环内)中抽象出确定需要处理哪些文件名的逻辑(循环外)。

【讨论】:

  • 大声笑我只是在写这个。我想2秒太慢了。 +1
  • 哈哈,十分钟前的另一个问题让我对自己的“两秒两慢”感觉好多了:D
【解决方案4】:

LINQ Contains 操作会更简洁(假设 usedFileNames 是 List&lt;string&gt;):

FileInfo[] filePaths = di.GetFiles("*.pdf");
foreach(FileInfo myInfo in filePaths)
{
    if (!usedFileNames.Contains(myInfo.Name))
    {
        PDFReaderChooser chooser = new PDFReaderChooser(myInfo.Name);
        usedFileNames.Add(myInfo.Name);
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    相关资源
    最近更新 更多