C# 使用FileInfo类移动成对文件后,需要一种优雅的方法来从文件夹中移动孤立文件

C# 使用FileInfo类移动成对文件后,需要一种优雅的方法来从文件夹中移动孤立文件,c#,fileinfo,C#,Fileinfo,我有一个文件夹,从中移动成对的相关文件(xml和pdf)。其他文件可以随时存放到此文件夹中,但该实用程序每10分钟左右运行一次。我们可以使用FileSystemWatcher类,但由于内部原因,我们不支持此实用程序 在每次运行期间,我使用System.IO.FileInfo类读取文件夹中的所有文件(仅为xml和pdf)。一旦我在FileInfo对象中有了这些文件,我就遍历这些文件,将匹配项移动到一个工作文件夹中。完成后,我想将任何未配对但位于FileInfo对象中的文件移动到故障文件夹 既然我似

我有一个文件夹,从中移动成对的相关文件(xml和pdf)。其他文件可以随时存放到此文件夹中,但该实用程序每10分钟左右运行一次。我们可以使用FileSystemWatcher类,但由于内部原因,我们不支持此实用程序

在每次运行期间,我使用System.IO.FileInfo类读取文件夹中的所有文件(仅为xml和pdf)。一旦我在FileInfo对象中有了这些文件,我就遍历这些文件,将匹配项移动到一个工作文件夹中。完成后,我想将任何未配对但位于FileInfo对象中的文件移动到故障文件夹

既然我似乎无法从FileInfo对象中删除项(或者我缺少了一些东西),那么(1)从Directory class.GetFiles中使用字符串数组,(2)从FileInfo对象中创建一个字典,并在迭代过程中删除其中的值,或者(3)是否有更优雅的方法使用LINQ或其他方法

以下是迄今为止的代码:

internal static bool CompareXMLandPDFFileNames(FileInfo[] xmlFiles, FileInfo[] pdfFiles, string xmlFilePath)
    {
        string workingFilePath = xmlFilePath + @"\WORKING";            

        if (xmlFiles.Length > 0)
        {
            foreach (var xmlFile in xmlFiles)
            {
                string xfn = xmlFile.Name; //xml file name
                string pdfName = xfn.Substring(0,xfn.IndexOf('_')) + ".pdf"; //parsed pdf file name contained in xml file name

                foreach (var pdfFile in pdfFiles)
                {
                    string pfn = pdfFile.Name; //pdf file name
                    if (pfn == pdfName)
                    {
                        //move xml and pdf files to working folder...
                        FileInfo xmlInfo = new FileInfo(xmlFilePath + xfn);
                        FileInfo pdfInfo = new FileInfo(xmlFilePath + pfn);
                        if (!File.Exists(workingFilePath + xfn))
                        {
                            xmlInfo.MoveTo(workingFilePath + xfn);                                
                        }

                        if (!File.Exists(workingFilePath + pfn))
                        {
                            pdfInfo.MoveTo(workingFilePath + pfn);
                        }                            
                    }
                }
            }

            //all files in the file objects should now be moved to working folder, if not, fix orphans...
        }

        return true;
    }

老实说,我觉得这个问题有点糟糕。这个问题以一种非常复杂的方式陈述。我认为工作流的设计应该更加健壮和确定。(例如,为什么不首先上传压缩集的文件对?)

(没有“某人”最有可能“以前一定没有来过这里”)

以下是一些随机改进:

using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;

namespace O
{
    static class X
    {
        private static readonly Regex _xml2pdf = new Regex("(_.*).xml$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        internal static void MoveFileGroups(string uploadFolder)
        {
            string workingFilePath = Path.Combine(uploadFolder, "PROGRESS");

            var groups = new DirectoryInfo(uploadFolder)
                .GetFiles()
                .GroupBy(fi => _xml2pdf.Replace(fi.Name, ".pdf"), StringComparer.InvariantCultureIgnoreCase)
                .Where(group => group.Count() >1);

            foreach (var group in groups)
            {
                if (!group.Any(fi => File.Exists(Path.Combine(workingFilePath, fi.Name))))
                    foreach (var file in group)
                        file.MoveTo(Path.Combine(workingFilePath, file.Name));
            }
        }

        public static void Main(string[]args)
        {
        }
    }
}
  • 使用可读的名称(说出你的意思)
  • 如果文件名不包含“\ux”,IndexOf将返回-1;随机上传文件名可能会使过程失败
  • Windows上的句柄文件名不区分大小写
  • 不要手动执行路径concats(您可能会意外地生成UNC路径,并且代码的可移植性较差)
  • 不要假设一个xml映射到一个pdf:命名方案意味着许多xml映射到同一个pdf名称。此实现允许这样做(或者您可以通过拒绝
    组来检测情况。其中(g=>g.Count()>2
  • 仅以原子方式移动组(!):如果组中的任何一个文件存在于目标目录中,请不要移动任何文件(否则您将遇到竞争条件,即在上载最后一个文件(完全)之前移动了组的一部分,并且由于不再检测到该组,因此将永远不会移动该文件
  • 其他项目(待办事项)

    • 不要传递冗余参数。如果需要筛选,可以传递FI[]而不是raw GetFiles()调用
    • 执行错误处理,特别是:
      • 处理IO异常
      • 上载过程中可能会出现锁定错误(测试它或最终导致文件损坏);您需要自动处理这些错误(即,除非可以移动所有文件,否则不要移动组中的任何文件;这将有点棘手)
        • 测试您的代码(我的示例中没有一个经过测试;它只是在使用mono的linux上编译的)

    我刚刚注意到您想对其余的文件做些什么。我不知道为什么(您只需通过在另一个文件配对之前删除一个文件来强化我描述的竞争条件)。但是你可以很容易地在示例的基础上进行构建,以实现你的愿望。处理其余的文件很容易。为什么不添加它呢?@Gabe,因为我认为这是一个坏主意(正如我所解释的)。为了过滤掉无关的文件,我建议你可以传递一个FI[],而不是原始的GetFiles()如果需要筛选,请致电,感谢您发布此完整答案,尽管您认为问题很糟糕。这将帮助我创建更好的解决方案。我特别同意文件的原子移动。我还发现了一些有用的相关内容。待办事项列表非常有用。