2009-05-26 13 views
4

Ich entwickle eine Windows-Anwendung in VS2005 mit C#. In meinem Projekt erzeuge ich dlls und speichere sie in einem Verzeichnis. Die DLLs werden als TestAssembly1, TestAssembly2, TestAssembly3 usw. benannt.Wie persistente Werte von Dateien in einem Verzeichnis gespeichert werden?

Also überlegen, ob die oben genannten drei DLLs im Verzeichnis sind. Das nächste Mal, wenn der Benutzer mein Projekt verwendet, muss ich dlls wie TestAssembly4, TestAssembly5 usw. generieren.

Also wie kann ich die Anzahl der DLLs in den Ordner speichern und sie erhöhen, wenn das Projekt das nächste Mal verwendet wird?

Das Verzeichnis kann sogar andere Dateien als dlls enthalten. Wie kann ich das tun?

Antwort

10

Persönlich würde ich eine binäre Suche verwenden, um die nächste Versammlung zu finden. ..

  • Anfang n = 1
  • tut TestAssembly1.dll zu existieren? (Ja)
  • ist TestAssembly2.dll vorhanden? (Ja)
  • ist TestAssembly4.dll vorhanden? (Ja)
  • ist TestAssembly8.dll vorhanden? (Ja)
  • ist TestAssembly16.dll vorhanden? (Ja)
  • ist TestAssembly32.dll vorhanden? (No)

und keine Verwendung binäre Suche zwischen 16 und 32:

  • tut TestAssembly24.dll zu existieren? (Ja)
  • ist TestAssembly28.dll vorhanden? (Ja)
  • ist TestAssembly30.dll vorhanden? (no)
  • ist TestAssembly29.dll vorhanden? (Ja)

so verwenden TestAssembly30.dll

Dies vermeidet die Notwendigkeit, die Zählung getrennt zu halten, so wird es auch funktionieren, wenn Sie alle Dateien löschen - und die binäre Suche bedeutet, dass Sie dies nicht tun habe eine schlechte Leistung.

Nicht getestet, aber etwas wie unten; auch beachten, dass etwas auf Datei Existenz basierte sofort eine Race-Bedingung (obwohl in der Regel ein sehr schlankes eins):

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

Es hängt von der Problemdomäne ab. Brauchen Sie eine spezielle Handhabung für Lücken? Erwarten Sie unter normalen Umständen nur eine Handvoll Dateien im Verzeichnis.(eine vollständige Liste von Dateien in einem Verzeichnis zu bekommen ist viel viel billiger als die gleiche Menge von file.exist Operationen) –

+0

@ sambo99 - "eine vollständige Liste zu bekommen .... ist viel billiger"; das hängt von der Anzahl der Dateien im Verzeichnis ab ... –

+0

@ sambo99; Beachten Sie, dass es nur 6 file.Exists Tests für die ersten 32 Dateien gibt. Bei diesem Ansatz müssen Sie keine Liste der Dateien abrufen. –

1

Anstatt viel zu überprüfen, ob eine Datei bereits vorhanden Sie eine Liste aller Baugruppen zu bekommen, extrahieren ihre IDs und geben die höchste ID + 1 zurück:

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 ExtractIdsFromAssemblyList(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; 
      } 
     } 
    } 
} 
Verwandte Themen