I am trying to copy (an array of file extensions) to a folder (and to this folder which I copy to make a 100MB limit), if the limit is exceeded the files in the folder, stop copying! Here is the code:

public static void GetFilesList() { long DS = 1000000; string[] extens = { ".txt", ".doc", ".cs", ".ico", ".Dll", ".Html", ".Htm", ".Xml", ".Php", ".png", ".jpg", ".gif" }; if (DirSize(new DirectoryInfo(Easy.GooVer), DS) > DS) { foreach (string fileName in Directory.GetFiles(Easy.GooVer, "*.*", SearchOption.AllDirectories)) { string ext = Path.GetExtension(fileName); if (Array.IndexOf(extens, ext) >= 0) { try{ File.Copy(fileName, Path.Combine(Easy.str1, Path.GetFileName(fileName)), true);}catch { } } } } } public static long DirSize(DirectoryInfo d, long aLimit = 0) { long Size = 0; FileInfo[] fis = d.GetFiles(); foreach (FileInfo fi in fis) { Size += fi.Length; if (aLimit > 0 && Size > aLimit) return Size; } DirectoryInfo[] dis = d.GetDirectories(); foreach (DirectoryInfo di in dis) { Size += DirSize(di, aLimit); if (aLimit > 0 && Size > aLimit) return Size; } return (Size); } 
  • 3
    And the question is what? - Monk
  • one
    And why do you have if (DirSize(new DirectoryInfo(Easy.GooVer), DS) > DS) ? Are you sure about > ? - VladD
  • one
    @Monk; While copying files to a folder, make a restriction. If the folder exceeds the allowed size of 100MB, then finish copying the files to the folder))) - GooliveR
  • Just save the current size to a variable, before copying the file, add its size to it and check if the limit is exceeded. Just do not forget to subtract the size into catch {} in case the file could not be copied (although it would be better to check if the copied file exists at all, and if so, check its size). - Surfin Bird
  • @VladD, I suggested making a check through the while(true) , but apparently it does not channel, I don’t know where to go) - GooliveR

2 answers 2

It is possible to solve this problem through the ITERATOR pattern, although it may be more difficult and more writings, but this is a classic!

We need an Enumerator

 internal class FilesEnumerator : IEnumerator<FileInfo> { private string _StartPath; private IEnumerator<string> _FileEnumerator; //ctor public FilesEnumerator(string startPath, string searchPattern) { _StartPath = startPath; var files = Directory.EnumerateFiles(_StartPath, searchPattern, SearchOption.AllDirectories); _FileEnumerator = files.GetEnumerator(); } public FileInfo Current { get { return new FileInfo(_FileEnumerator.Current); } } object IEnumerator.Current { get { return this.Current; } } public bool MoveNext() { return _FileEnumerator.MoveNext(); } public void Reset() { _FileEnumerator.Reset(); } public void Dispose() { _FileEnumerator.Dispose(); } } 

further locator

 public class FilesLocator : IEnumerable<FileInfo> { private string _StartPath; private string _SearchPattern; //ctor public FilesLocator(string startPath, string searchPattern = "*.*") { if (String.IsNullOrEmpty(startPath)) throw new ArgumentException($"{nameof(startPath)} не может быть пустым"); if (String.IsNullOrEmpty(startPath)) throw new ArgumentException($"{nameof(searchPattern)} не может быть пустым"); _StartPath = startPath; _SearchPattern = searchPattern; } public IEnumerator<FileInfo> GetEnumerator() { return new FilesEnumerator(_StartPath, _SearchPattern); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } 

Well, you can use it

 [TestMethod()] public void FilesLocatorTest() { string fromC = @"D:\Temp"; string toC = @"C:\Temp"; //вы уж извините, я тут свои другие расширения подставил List<string> extensions = new List<string>() { ".json", ".txt" }; //опять же можете др. лимит прописать long limit = 100000; var files = new FilesLocator(fromC); foreach (var file in files) { string ext = Path.GetExtension(file.Name); int id = extensions.IndexOf(ext); if ( id < 0) continue; if ((limit -= file.Length) < 0) break; try { file.CopyTo(Path.Combine(toC, file.Name)); } catch { // } } } 

    Try, for example, like this:

     long copiedSoFar = 0; foreach (string fileName in Directory.GetFiles(Easy.GooVer, "*.*", SearchOption.AllDirectories)) { string ext = Path.GetExtension(fileName); if (Array.IndexOf(extens, ext) < 0) continue; try { var fileSize = new FileInfo(fileName).Length; if (copiedSoFar + fileSize > DS) continue; // другие файлы могут ещё влезть File.Copy(fileName, Path.Combine(Easy.str1, Path.GetFileName(fileName)), true); copiedSoFar += fileSize; } catch { // тут надо сделать что-то разумное } } 
    • And what about while(true) , I just have doubts that he will not check it)), well, I'll try, ATP). - GooliveR
    • Try it, it should work on the idea. - VladD
    • I tried your method, files are copied only from 1 directory, not all folders pass through. - GooliveR
    • @ArteS: It can not be, you have not accidentally forgotten SearchOption.AllDirectories ? Show the code you tried. - VladD
    • @VladD, there is mileage in the subfolders, but restoring the folder structure at the new location is not. Perhaps this is meant. - Monk