0

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

我使用 System.IO.FileInfo 类在每次运行期间读取文件夹中的所有文件(只会是 xml 和 pdf)。在 FileInfo 对象中获得文件后,我会遍历文件,将匹配项移动到工作文件夹。完成后,我想将任何未配对但位于 FileInfo 对象中的文件移动到失败文件夹。

由于我似乎无法从 FileInfo 对象中删除项目(或者我遗漏了一些东西),(1)使用 Directory 类 .GetFiles 中的字符串数组,(2)从 FileInfo 对象创建一个 Dictionary 和在迭代期间从中删除值,或者(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;
    }
4

1 回答 1

0

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

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

以下是一些随机改进:

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)
        {
        }
    }
}
  1. 使用易读的名称(说出你的意思)
  2. 如果文件名不包含“_”,IndexOf 返回 -1;随机上传文件名可能导致程序失败
  3. 在 Windows 上处理文件名不区分大小写
  4. 不要手动进行路径连接(您可能会意外制造 UNC 路径,并且您的代码的可移植性较差)
  5. 不要假设一个 xml 将映射到一个 pdf:命名方案意味着许多 xml 映射到同一个 pdf 名称。此实现允许(或者您可以通过拒绝来检测情况groups.Where(g => g.Count()>2
  6. 仅以原子方式移动组(!):如果组中的任何一个文件存在于目标目录中,请不要移动任何文件(否则您将遇到竞争条件,其中组的一部分在最后一个文件之前移动(完全)已上传,并且永远不会移动,因为不再检测到该组

其他项目(待办事项)

  • 不要传递多余的参数。如果你想过滤,你可以传递一个 FI[] 而不是原始的 GetFiles() 调用。
  • 进行错误处理,特别是:
    • 处理 IO 异常
    • 在上传过程中可能会出现锁定错误(测试它或最终导致文件损坏);您需要自动处理这些(即,除非可以移动所有文件,否则不要移动组中的任何文件;这会有些棘手)
      • 测试你的代码(我的样本都没有经过测试;它只是在 linux 上用单声道编译)
于 2011-03-23T02:05:56.907 回答