SyncMaster
SyncMaster

Reputation: 9916

How to store values persistenly of files in a directory?

I'm developing a Windows application in VS2005 using C#. In my project, I generate dlls and store them in a directory. The dlls will be named as TestAssembly1, TestAssembly2, TestAssembly3 etc.

So consider if the above three dlls are in the directory. The next time the user uses my project, I need to generate dlls like TestAssembly4, TestAssembly5 etc.

So how can I store the count of the dlls in the folder and increment them when the project is used the next time?

The directory can even contain files other than dlls. So how can I do this?

Upvotes: 5

Views: 4009

Answers (3)

VVS
VVS

Reputation: 19604

Instead of lots of checking if a file already exist you can get a list of all assemblies, extract their ID's and return the highest ID + 1:

int nextId = GetNextIdFromFileNames(
               "pathToAssemblies", 
               "TestAssembly*.dll", 
               @"TestAssembly(\d+)\.dll");

[...]

public int GetNextIdFromFileNames(string path, string filePattern, string regexPattern)
{
    // get all the file names
    string[] files = Directory.GetFiles(path, filePattern, SearchOption.TopDirectoryOnly);

    // extract the ID from every file, get the highest ID and return it + 1
    return ExtractIdsFromFileList(files, regexPattern)
           .Max() + 1;
}

private IEnumerable<int> ExtractIdsFromFileList(string[] files, string regexPattern)
{
    Regex regex = new Regex(regexPattern, RegexOptions.IgnoreCase);

    foreach (string file in files)
    {
        Match match = regex.Match(file);
        if (match.Success)
        {
            int value;
            if (int.TryParse(match.Groups[1].Value, out value))
            {
                yield return value;
            }
        }
    }
}

Upvotes: 2

Marc Gravell
Marc Gravell

Reputation: 1062550

Personally I'd use a binary search to find the next assembly...

  • start n=1
  • does TestAssembly1.dll exist? (yes)
  • does TestAssembly2.dll exist? (yes)
  • does TestAssembly4.dll exist? (yes)
  • does TestAssembly8.dll exist? (yes)
  • does TestAssembly16.dll exist? (yes)
  • does TestAssembly32.dll exist? (no)

and no use binary search between 16 and 32:

  • does TestAssembly24.dll exist? (yes)
  • does TestAssembly28.dll exist? (yes)
  • does TestAssembly30.dll exist? (no)
  • does TestAssembly29.dll exist? (yes)

so use TestAssembly30.dll

This avoids the need to keep the count separately, so it'll work even if you delete all the files - and the binary search means you don't have too bad performance.

Untested, but something like below; also note that anything based on file existence is immediately a race condition (although usually a very slim one):

    static string GetNextFilename(string pattern) {
        string tmp = string.Format(pattern, 1);
        if (tmp == pattern) {
            throw new ArgumentException(
                 "The pattern must include an index place-holder", "pattern");
        }
        if (!File.Exists(tmp)) return tmp; // short-circuit if no matches

        int min = 1, max = 2; // min is inclusive, max is exclusive/untested
        while (File.Exists(string.Format(pattern, max))) {
            min = max;
            max *= 2;
        }

        while (max != min + 1) {
            int pivot = (max + min) / 2;
            if (File.Exists(string.Format(pattern, pivot))) {
                min = pivot;
            }
            else {
                max = pivot;
            }
        }
        return string.Format(pattern, max);
    }

Upvotes: 12

samjudson
samjudson

Reputation: 56853

You would just use Directory.GetFiles, passing in a pattern for the files you want to return:

http://msdn.microsoft.com/en-us/library/wz42302f.aspx

string[] files = Directory.GetFiles(@"C:\My Directory\", "TestAssembly*.dll");

Upvotes: 4

Related Questions