创建文件夹结构,每个文件夹包含x个文件

时间:2010-12-07 13:51:28

标签: c# winforms file-io

我有很多文件夹,每个文件夹超过500,000个。我想将它们分解为10,000(或50,000或5,000或用户定义的任何文件夹)的文件夹。

我的逻辑显然有问题,因为目前它只是将我的所有文件移动到它创建的第一个文件夹中。我尝试过使用foreach和where的不同组合,但没有运气。

        //Find all the files to move
        string[] files = Directory.GetFiles(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly); 
        //Use selects the number of files to go in each folder
        long h = long.Parse(tbFilePerFolder.Text);
        //Used later
        long i = 0;
        //Used later
        long j = 0;
        //Get the number of folders to create
        long k = files.Count() / h;

        //Report back the number of files found
        lblFilesFound.Text = "Files Found: " + files.Count();

        //Create the necessary number of folders, plus 1 to pick up remainders
        while (j <= k + 1)
        {
            Directory.CreateDirectory(textBox1.Text + @"\" + j.ToString("00000"));
            lblFoldersCreated.Text = "Folders Created: " + j;
            j++;
        }

        //Get each folder that's just been created
        string[] folders = Directory.GetDirectories(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly);

        //For each of those folders...
        foreach (string folder in folders)
        {
            //While there is less than the requested number of folders...
            while (i <= h)
            {
                //Get a list of the currently existing files
                string[] files2 = Directory.GetFiles(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly); 

                //And iterate through it, moving to the defined directory
                foreach (string file in files2)
                {
                    File.Move(file, folder + @"\" + Path.GetFileName(file));
                    lblFilesMoved.Text = "Files Moved: " + i;
                    i++;
                }
            }
        }

4 个答案:

答案 0 :(得分:2)

你最内层的循环也必须检查i < h

foreach (string file in files2)
{
   File.Move(file, folder + @"\" + Path.GetFileName(file));
   lblFilesMoved.Text = "Files Moved: " + i;
   i++;
   if (i > h) 
      break;
}

我还注意到你打电话给Directory.GetFiles()两次,而且费用非常高 考虑重新使用第一个列表,并在搬家后寻找新人。

如果您可以使用Fx4,那么Directory.EnumerateFiles()可以对包含500k文件的文件夹产生很大影响。但是你必须更多地调整你的代码。

答案 1 :(得分:1)

你为什么不这样做:

int j=0;  
foreach (string filename in Directory.GetFiles(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly)
{
  File.Move(filename , Path.Combine(textBox1.Text + j.ToString("0000"), Path.GetFileName(file));
  j = (j + 1)%(k + 1);
}

在这种情况下,连续文件将放在不同的文件夹中。我不知道你的情况是否重要。

答案 2 :(得分:1)

您遇到的问题是以下代码永远不会跳出while循环,直到所有文件都移到您的文件夹1:

while (i <= h) 
{
  string[] files2 = Directory.GetFiles(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly); 
  foreach (string file in files2)
     {
        File.Move(file, folder + @"\" + Path.GetFileName(file));
        lblFilesMoved.Text = "Files Moved: " + i;
        i++; //this will never jump out the while loop until all files moved to your folder1
      }
}

相反,您应该使用以下代码:(尽可能接近原始代码)

    string[] files = Directory.GetFiles(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly); 

    long h = long.Parse(tbFilePerFolder.Text);
    long i = 0;
    long j = 0;
    long k = files.Count() / h;
    lblFilesFound.Text = "Files Found: " + files.Count();
    while (j <= k + 1)
           {
                Directory.CreateDirectory(textBox1.Text + @"\" + j.ToString("00000"));
                lblFoldersCreated.Text = "Folders Created: " + j;
                j++;
            } 

    string[] folders = Directory.GetDirectories(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly) 

    //do you really need to search again? or maybe you can just use files instead?
    string[] files2 = Directory.GetFiles(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly); 


     ind d=0;                   
     foreach (string file in files2)
     { 
       string folder=folders[d];
       while (i <= h)
       {
          File.Move(file, folder + @"\" + Path.GetFileName(file));
          lblFilesMoved.Text = "Files Moved:" + i;
          i++; 
       }
       d++;
       i=0;

      }

答案 3 :(得分:0)

我最终选择了上面的所有内容,所以非常感谢这些想法! (也使用Directory.EnumerateFiles。)我意识到逻辑出错的地方并且停止了两次调用GetFiles。

        string[] folders = Directory.GetDirectories(textBox1.Text, "*.*", SearchOption.TopDirectoryOnly);

        long d = 0;
        long c = 0;
        //And iterate through it, moving to the defined directory 
        while (d <= k)
        {
            while (i <= h)
            {
                try
                {
                    string folder = folders[d];
                    string file = files[c];
                    File.Move(file, folder + @"\" + Path.GetFileName(file));
                    c++;
                    i++;
                    lblFilesMoved.Text = "Files Moved: " + i;
                }
                catch (Exception f)
                {
                    MessageBox.Show(f.ToString());
                }
            }
            d++;
            i = 0;