【问题标题】:Deleting files using C# [closed]使用 C# 删除文件 [关闭]
【发布时间】:2015-03-04 14:40:11
【问题描述】:

我写了一个运动检测winform c#桌面应用。

运动帧以单独的 jpeg 格式保存到我的硬盘中。

我使用 4 台摄像机进行录制。这由变量表示:

   camIndex

每个 jpeg 都在一个文件结构下:

c:\年\月\日\时\分

以确保目录不会在每个目录中获取太多文件。

目的是让我的应用 24/7 全天候运行。应用可能会因系统重启或用户选择暂时关闭等原因而停止。

目前我有一个计时器,每 5 分钟运行一次,以删除超过 24 小时的文件。

我发现我的以下代码是内存密集型的,并且在几天的时间里 explorer.exe 已经在 RAM 内存中攀升。

我的运动应用程序需要一直打开,因此低内存占用对于这种“归档”至关重要...

以下代码很长,在我看来效率极低。有没有更好的方法可以实现我的目标?

我使用这个代码:

List<string> catDirs = Directory.EnumerateDirectories(Shared.MOTION_DIRECTORY, "*", SearchOption.TopDirectoryOnly).ToList();
for (int index = 0; index < catDirs.Count; index++)
{
   for (int camIndex = 0; camIndex < 4; camIndex++)
   {
       if (Directory.Exists(catDirs[index] + "\\Catalogues\\" + camIndex.ToString()))
       {
           List<string> years = GetDirectoryList(catDirs[index] + "\\Catalogues\\" + camIndex.ToString(), true);
           if (years.Count == 0)
           {
                Directory.Delete(catDirs[index]);
            }
            for (int yearIndex = 0; yearIndex < years.Count; yearIndex++)
            {
                DirectoryInfo diYear = new DirectoryInfo(years[yearIndex]);
                List<string> months = GetDirectoryList(years[yearIndex], true);
                if (months.Count == 0)
                {
                  Directory.Delete(years[yearIndex]);
                }
                for (int monthIndex = 0; monthIndex < months.Count; monthIndex++)
                {
                    DirectoryInfo diMonth = new DirectoryInfo(months[monthIndex]);
                    List<string> days = GetDirectoryList(months[monthIndex], true);
                    if (days.Count == 0)
                    {                          
                        Directory.Delete(months[monthIndex]);                           
                    }
                    for (int dayIndex = 0; dayIndex < days.Count; dayIndex++)
                    {
                        DirectoryInfo diDay = new DirectoryInfo(days[dayIndex]);
                        List<string> hours = GetDirectoryList(days[dayIndex], true);
                        if (hours.Count == 0)
                        {
                            Directory.Delete(days[dayIndex]);                              
                        }
                        for (int hourIndex = 0; hourIndex < hours.Count; hourIndex++)
                        {
                            DirectoryInfo diHour = new DirectoryInfo(hours[hourIndex]);
                            List<string> mins = GetDirectoryList(hours[hourIndex], false);
                            if (mins.Count == 0)
                            {
                                Directory.Delete(hours[hourIndex]);
                            }
                            for (int minIndex = 0; minIndex < mins.Count; minIndex++)
                            {
                                bool deleteMe = false;
                                DirectoryInfo diMin = new DirectoryInfo(mins[minIndex]);
                                DateTime foundTS = new DateTime(Convert.ToInt16(diYear.Name), Convert.ToInt16(diMonth.Name), Convert.ToInt16(diDay.Name),
                                Convert.ToInt16(diHour.Name), Convert.ToInt16(diHour.Name), 00);
                                double minutesElapsed = upToDateDate.Subtract(foundTS).TotalMinutes;
                               if (minutesElapsed > diff)
                               {
                                   deleteMe = true;
                               }
                               if (deleteMe)
                               {
                                   Directory.Delete(mins[minIndex], true);
                               }
                           }
                       }
                   }
               }
           }
       }
   }

【问题讨论】:

  • 这是一个 很多 嵌套的 for 循环!如果您准确解释代码的作用,您的问题会更清楚。目录结构是什么?文件是如何命名的?你用什么来确定他们的年龄?
  • @AndrewSimpson - 给你:stackoverflow.com/questions/268132/…
  • 在时间范围内看起来确实像嵌套目录。如果您每 24 小时冲洗一次所有东西,为什么需要它?如果您不必像那样循环,可以将代码简化为 2-3 行。
  • @AndrewSimpson:当程序重新启动时,您可以简单地重建队列。只需扫描您的目录并重建队列。
  • 不知道这是否有用,但您可以查看File.GetCreationTimemsdn.microsoft.com/en-us/library/…

标签: c# file-io


【解决方案1】:

这可能会有所帮助,但未测试效率:

Directory
.GetFiles(@"[Path of your root directory]", "*.*", SearchOption.AllDirectories)
.Where(item =>
{
    try
    {
        var fileInfo = new FileInfo(item);
        return fileInfo.CreationTime < DateTime.Now.AddHours(-24);
    }
    catch (Exception)
    {
        return false;
    }
})
.ToList()
.ForEach(File.Delete);

确保添加正确的异常处理并避免僵尸尝试/空捕获(不推荐)

【讨论】:

  • 我会避免使用ToList 并使用foreach 循环。
  • 同意,这可能有助于节省一些 CPU 使用率,尤其是当列表变大时。
  • 对于 2.2Gb 的文件(每个文件权重 10kb,这意味着 很多),逐个枚举它们会非常低效,非常 .这是 5 分钟时间范围内的大量 I/O 操作。我认为在目录级别烧掉东西是个好方法(尽管实施得很糟糕),而且应该在更长的时间范围内。
  • 大小不重要,但数量重要。如果你真的想枚举所有文件而不是炸毁一个文件夹,我可能会在那里扔一个 Parallel.ForEach 来加快速度。
  • @Pierre-LucPineault - 是的,Parallel.ForEach 将是处理大量文件的明智方法 - msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx(抄送:Andrew Simpson)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2014-12-09
  • 2016-01-09
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多