【问题标题】:Moving files into subfolders (n files in each subfolder)将文件移动到子文件夹(每个子文件夹中有 n 个文件)
【发布时间】:2019-06-24 07:11:59
【问题描述】:

我有一个小问题要解决。我有一个包含很多文件的文件夹。我希望它以这样一种方式将它隔离到子文件夹中,即每个子文件夹都包含一定数量的文件。例如。我有 1500 个文件,我想将它移到 15 个子文件夹中(每个文件夹中有 100 个文件)。子文件夹的名称是 wahtever 这不是问题。我不知道如何使用数组来移动它,我不知道。

我从该文件夹中读取了一个文件列表并创建了一个这样的数组:

string path = @"E:\test_folder";
string path2 = @"E:\test_folder\1";

string[] files_array = Directory.GetFiles(path);

然后我可以像这样移动文件:

foreach (file in files_array){

     File.Move(System.IO.Path.Combine(path, file), System.IO.Path.Combine(path2, file));

}

但是我如何自动创建文件夹并仅移动一定数量的文件然后创建新文件夹等。我尝试这样做,但是我必须刷新我的数组,所以我认为这不是一个好主意。

while (files_array.Lenght > 0){

    foreach (file in files_array.Take(50)){

     File.Move(System.IO.Path.Combine(path, file), System.IO.Path.Combine(path2, file));
}
string[] files_array = Directory.GetFiles(path);}

我还考虑将所有数组写入 txt 临时文件,然后逐行读取并移动文件(这样我就不必刷新数组),但我不知道该怎么做。 最好的解决方案是什么?

【问题讨论】:

  • 你熟悉Take。你熟悉Skip吗? Take 50. Skip 0. 下一次迭代,Take 50. Skip 50. 等等。
  • @DanielMann,这不是无效吗?
  • @vasily.sib:你可以缓存它。对 1500 个项目的性能影响很小
  • @Stefan,您能否说明一下您所说的 “缓存” 是什么意思。对于 1500 个项目,您将拥有 30 批 50 个项目和 22 500 个无意义的迭代项目。
  • 这将在 400 毫秒内执行 - 让我们稍等一下:与文件的移动相比,这是一个非常小的操作

标签: c# .net


【解决方案1】:

所以,您知道如何移动文件(使用File.Move(..)),您所需要的只是批量遍历文件名数组。一种方法是Skip/Take

var i = 0;
var batchSize = 50;
var iterationsCount = files_array / batchSize + 1;

while (i < iterationsCount)
{
    var batch = files_array.Skip(i * batchSize).Take(batchSize);
    // do something with this batch...
}

但这完全无效。您将在每个循环中无缘无故地运行您的files_array 的一部分。


另一种方法是为IEnumerable&lt;T&gt; 创建一个扩展方法,如下所示:

public static class IEnumerableExtension
{
    public static IEnumerable<IEnumerable<T>> InBatches<T>(this IEnumerable<T> enumerable, int batchSize)
    {
        var batch = new List<T>(batchSize);
        var i = 0;

        foreach (var item in enumerable)
        {
            batch.Add(item);
            if (++i == batchSize)
            {
                // our batch is complete - yield return and create a new one
                yield return batch;
                batch = new List<T>(batchSize);
                i = 0;
            }
        }

        // something left in batch
        if (i != 0)
            yield return batch;
    }
}

现在你可以这样使用扩展了:

foreach (var batch in files_array.InBatches(50))
{
    // do something with this batch...
}

【讨论】:

  • 我不同意totally这个词;来自 cmets:我想知道 skip 是否真的会迭代。可以显示出处吗?
  • @Stefan SkipTake 不是由他们自己迭代你的枚举,但是当 you 实际上迭代 Skip(n).Take(m) 的结果时,你首先 @987654322 @ 然后是take m itemsTake(m) 部分没问题,因为你确实需要这 m 个项目,但是 Skip(n) 部分没用。
  • 另外,如果我按 N 计算多个项目,Skip / Take 将需要 N^2 更多时间。因此,如果 1 500 件物品需要 400 毫秒 - 15 000 件物品需要 40 秒,150 000 件物品需要 1 小时。
【解决方案2】:

我的建议是尝试获取文件夹中的所有文件名并将它们转换为字符串数组并使用for循环

试试这个代码

public static void Main(string[] args){
      DirectoryInfo d = new DirectoryInfo(@"D:\Test");//Assuming Test is your Folder
      FileInfo[] Files = d.GetFiles("*.txt"); //Getting Text files

      int tempCount = 0;
      string tempFolderName = "TestFolder";
      int tempCountFolder = 0;

      for (int i = 0; i < Files.Length; i++)
      {
        if (tempCount <= 50){
          Files[i].MoveTo($@"{tempFolderName}{tempCountFolder}");
        } else {
          tempCount = 0;
          tempCountFolder += 1;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2022-10-25
    • 1970-01-01
    • 2011-04-24
    • 2017-05-04
    • 2021-10-16
    • 2015-11-22
    • 2016-01-25
    • 2021-08-02
    相关资源
    最近更新 更多