Создайте структуру папок с x количеством файлов в папке - PullRequest
2 голосов
/ 07 декабря 2010

У меня есть несколько папок с более чем 500 000 элементов в каждой. Я хочу разбить их на папки по 10000 (или 50000, или 5000, или что угодно, что определит пользователь).

Очевидно, что в моей логике что-то не так, потому что в настоящий момент она просто перемещает все мои файлы в первую созданную папку. Я пробовал играть с разными комбинациями foreach и где, но не повезло.

        //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 ]

2 голосов
/ 07 декабря 2010

Ваш внутренний цикл также должен проверять 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 голос
/ 07 декабря 2010

Проблема, с которой вы столкнулись, заключается в том, что следующий код никогда не выйдет из цикла 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;

      }
1 голос
/ 07 декабря 2010

почему бы тебе не сделать что-то вроде:

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);
}

В этом случае последовательные файлы будут помещены в разные папки. Я не знаю, важно ли это в вашем случае.

0 голосов
/ 07 декабря 2010

Я закончил тем, что пошел чуть-чуть всего выше, поэтому большое спасибо за идеи!(Также использовал 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...