2012-10-24 19 views
42

Mój kod C# generuje kilka plików tekstowych na podstawie danych wejściowych i zapisanych w folderze. Zakładam również, że nazwa pliku tekstowego będzie taka sama jak wejście. (Wejście zawiera tylko litery) Jeśli dwa pliki mają taką samą nazwę, to po prostu zastępują poprzedni plik. Ale chcę zachować oba pliki.Automatycznie zmieniaj nazwę pliku, jeśli już istnieje w systemie Windows

Nie chcę dodawać bieżącej daty ani numeru losowego do nazwy drugiego pliku. Zamiast tego chcę zrobić to w taki sam sposób, jak robi to Windows. Jeśli nazwa pliku fisrt to AAA.txt, wówczas nazwa drugiego pliku to AAA (2) .txt, trzecią nazwą pliku będzie AAA (3) .txt ..... N-ta nazwa pliku będzie AAA (N) .txt .

string[] allFiles = Directory.GetFiles(folderPath).Select(filename => Path.GetFileNameWithoutExtension(filename)).ToArray(); 
     foreach (var item in allFiles) 
     { 
      //newFileName is the txt file which is going to be saved in the provided folder 
      if (newFileName.Equals(item, StringComparison.InvariantCultureIgnoreCase)) 
      { 
       // What to do here ?     
      } 
     } 

Odpowiedz

102

Spowoduje to sprawdzenie istnienia plików z tempFileName i zwiększanie liczby o jeden, dopóki nie znajdzie nazwy, która nie istnieje w katalogu.

int count = 1; 

string fileNameOnly = Path.GetFileNameWithoutExtension(fullPath); 
string extension = Path.GetExtension(fullPath); 
string path = Path.GetDirectoryName(fullPath); 
string newFullPath = fullPath; 

while(File.Exists(newFullPath)) 
{ 
    string tempFileName = string.Format("{0}({1})", fileNameOnly, count++); 
    newFullPath = Path.Combine(path, tempFileName + extension); 
} 
+7

Rozszerzenie plików byłoby błędne, np. ** C: \ plik.txt ** stałoby się ** C: \ plik.txt (1) ** "itd. – flindeberg

+4

@flindeberg dobry połów. Wierzę, że poprawiłem to błąd: – cadrell0

+4

Dla przyszłego ref. mały haczyk, aby być świadomym: jeśli sprawdzany plik ma nazwę 'some name (1) some more text.txt', a plik już istnieje, jeśli zostanie poproszony o zachowanie obu plików Windows zmieni nazwę pliku 'some name (2) some more text.txt', a nie' some name (1) trochę więcej text (1) .txt' jak powyższy kod mógłby zrobić. –

1

Jak o właśnie:

int count = 1; 
String tempFileName = newFileName; 

foreach (var item in allFiles) 
{ 
    if (tempFileName.Equals(item, StringComparison.InvariantCultureIgnoreCase)) 
    { 
    tempFileName = String.Format("{0}({1})", newFileName, count++); 
    } 
} 

To będzie używać oryginalnej nazwy pliku, jeśli go tam nie ma, jeśli nie zajmie się nową nazwę pliku z indeksem w nawiasach (chociaż ten kod ISN nie uwzględniając rozszerzenia). Jeśli zostanie użyta nowo wygenerowana nazwa "text (001)", wówczas będzie ona wzrastać, aż znajdzie prawidłową, nieużywaną nazwę pliku.

+2

Musisz zwiększyć liczbę. Ponadto parametr 'tempFileName' nie jest ponownie sprawdzany względem poprzednich elementów. Zatem 'tempFileName' może zostać zmieniony na element, który został już sprawdzony i przekazany. – cadrell0

+0

@ cadrell0: oops dzięki ... taki był plan! Pisanie zbyt szybko. – Ian

+1

Nie uwzględnia to rozszerzenia pliku. Poniżej zamieściłem inny przykład. – Phill

3

Inne przykłady nie uwzględniają nazwy pliku/rozszerzenia.

Proszę bardzo:

public static string GetUniqueFilename(string fullPath) 
    { 
     if (!Path.IsPathRooted(fullPath)) 
      fullPath = Path.GetFullPath(fullPath); 
     if (File.Exists(fullPath)) 
     { 
      String filename = Path.GetFileName(fullPath); 
      String path = fullPath.Substring(0, fullPath.Length - filename.Length); 
      String filenameWOExt = Path.GetFileNameWithoutExtension(fullPath); 
      String ext = Path.GetExtension(fullPath); 
      int n = 1; 
      do 
      { 
       fullPath = Path.Combine(path, String.Format("{0} ({1}){2}", filenameWOExt, (n++), ext)); 
      } 
      while (File.Exists(fullPath)); 
     } 
     return fullPath; 
    } 
0

Można zadeklarować Dictionary<string,int> aby utrzymać liczbę razy każda nazwa pliku korzeń został zapisany. Po tym, na metodzie Save, po prostu zwiększyć licznik i dołączyć go do nazwy pliku Base:

var key = fileName.ToLower(); 
string newFileName; 
if(!_dictionary.ContainsKey(key)) 
{ 
    newFileName = fileName; 
    _dictionary.Add(key,0); 
} 
else 
{ 
    _dictionary[key]++; 
    newFileName = String.Format("{0}({1})", fileName, _dictionary[key]) 
} 

W ten sposób będziesz mieć licznik dla każdej odrębnej nazwy pliku: AAA (1), AAA (2); BBB (1) ...

0

Teraz działa dobrze. Dzięki chłopaki za odpowiedzi ..

string[] allFiles = Directory.GetFiles(folderPath).Select(filename => Path.GetFileNameWithoutExtension(filename)).ToArray(); 
     string tempFileName = fileName; 
     int count = 1; 
     while (allFiles.Contains(tempFileName)) 
     { 
      tempFileName = String.Format("{0} ({1})", fileName, count++); 
     } 

     output = Path.Combine(folderPath, tempFileName); 
     string fullPath=output + ".xml"; 
0
int count= 0; 

pliku jest nazwa pliku

while (File.Exists(fullpathwithfilename)) //this will check for existence of file 
{ 
// below line names new file from file.xls to file1.xls 
fullpathwithfilename= fullpathwithfilename.Replace("file.xls", "file"+count+".xls"); 

count++; 
} 
+0

Skąd czerpiesz "tempno"? – Frecklefoot

11

z tego kodu, jeśli nazwa pliku jest "Test (3) .txt", to będzie „Test (4) .txt ".

public static string GetUniqueFilePath(string filepath) 
{ 
    if (File.Exists(filepath)) 
    { 
     string folder = Path.GetDirectoryName(filepath); 
     string filename = Path.GetFileNameWithoutExtension(filepath); 
     string extension = Path.GetExtension(filepath); 
     int number = 1; 

     Match regex = Regex.Match(filepath, @"(.+) \((\d+)\)\.\w+"); 

     if (regex.Success) 
     { 
      filename = regex.Groups[1].Value; 
      number = int.Parse(regex.Groups[2].Value); 
     } 

     do 
     { 
      number++; 
      filepath = Path.Combine(folder, string.Format("{0} ({1}){2}", filename, number, extension)); 
     } 
     while (File.Exists(filepath)); 
    } 

    return filepath; 
} 
1
public static string AutoRenameFilename(FileInfo file) 
    { 
     var filename = file.Name.Replace(file.Extension, string.Empty); 
     var dir = file.Directory.FullName; 
     var ext = file.Extension; 

     if (file.Exists) 
     { 
      int count = 0; 
      string added; 

      do 
      { 
       count++; 
       added = "(" + count + ")"; 
      } while (File.Exists(dir + "\\" + filename + " " + added + ext)); 

      filename += " " + added; 
     } 

     return (dir + filename + ext); 
    } 
+1

Choć może to stanowić rozwiązanie tego problemu, byłoby lepiej, gdybyś mógł podać jakieś opracowanie lub wyjaśnienie, jak działa twój kod, lub jakiekolwiek mocne strony/wady, które może mieć. itp. –

1

szukałem rozwiązania, które byłoby przenieść plik, i upewnij się, że jeśli nazwa pliku docelowego nie jest już zajęta. Byłby zgodny z logiką systemu Windows i dołączał liczbę, z nawiasami po zduplikowanym pliku.

Górny odpowiedź, dzięki @ cadrell0, pomogła mi dojść do następującego rozwiązania:

/// <summary> 
    /// Generates full file path for a file that is to be moved to a destinationFolderDir. 
    /// 
    /// This method takes into account the possiblity of the file already existing, 
    /// and will append number surrounded with brackets to the file name. 
    /// 
    /// E.g. if D:\DestinationDir contains file name file.txt, 
    /// and your fileToMoveFullPath is D:\Source\file.txt, the generated path will be D:\DestinationDir\file(1).txt 
    /// 
    /// </summary> 
    /// <param name="destinationFolderDir">E.g. D:\DestinationDir </param> 
    /// <param name="fileToMoveFullPath">D:\Source\file.txt</param> 
    /// <returns></returns> 
    public string GetFullFilePathWithDuplicatesTakenInMind(string destinationFolderDir, string fileToMoveFullPath) 
    { 
     string destinationPathWithDuplicatesTakenInMind; 

     string fileNameWithExtension = Path.GetFileName(fileToMoveFullPath); 
     string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileToMoveFullPath); 
     string fileNameExtension = Path.GetExtension(fileToMoveFullPath); 

     destinationPathWithDuplicatesTakenInMind = Path.Combine(destinationFolderDir, fileNameWithExtension); 

     int count = 0; 
     while (File.Exists(destinationPathWithDuplicatesTakenInMind)) 
     { 
      destinationPathWithDuplicatesTakenInMind = Path.Combine(destinationFolderDir, $"{fileNameWithoutExtension}({count}){fileNameExtension}"); 
      count = count + 1; // sorry, not a fan of the ++ operator. 
     } 

     return destinationPathWithDuplicatesTakenInMind; 
    } 
0

Odnośnie komentarza Giuseppe po drodze okien zmienia nazwy plików, z którymi pracowałem w wersji, która znajdzie istniejący indeks tj(2) w nazwie pliku i odpowiednio zmienia nazwę pliku zgodnie z oknami. Przyjmuje się, że argument sourceFileName jest prawidłowy i zakłada się, że użytkownik ma pozwolenie na zapis w folderze docelowym:

using System.IO; 
using System.Text.RegularExpressions; 

    private void RenameDiskFileToMSUnique(string sourceFileName) 
    { 
     string destFileName = ""; 
     long n = 1; 
     // ensure the full path is qualified 
     if (!Path.IsPathRooted(sourceFileName)) { sourceFileName = Path.GetFullPath(sourceFileName); } 

     string filepath = Path.GetDirectoryName(sourceFileName); 
     string fileNameWOExt = Path.GetFileNameWithoutExtension(sourceFileName); 
     string fileNameSuffix = ""; 
     string fileNameExt = Path.GetExtension(sourceFileName); 
     // if the name includes the text "(0-9)" then we have a filename, instance number and suffix 
     Regex r = new Regex(@"\(\d+\)"); 
     Match match = r.Match(fileNameWOExt); 
     if (match.Success) // the pattern (0-9) was found 
     { 
      // text after the match 
      if (fileNameWOExt.Length > match.Index + match.Length) // remove the format and create the suffix 
      { 
       fileNameSuffix = fileNameWOExt.Substring(match.Index + match.Length, fileNameWOExt.Length - (match.Index + match.Length)); 
       fileNameWOExt = fileNameWOExt.Substring(0, match.Index); 
      } 
      else // remove the format at the end 
      { 
       fileNameWOExt = fileNameWOExt.Substring(0, fileNameWOExt.Length - match.Length); 
      } 
      // increment the numeric in the name 
      n = Convert.ToInt64(match.Value.Substring(1, match.Length - 2)) + 1; 
     } 
     // format variation: indexed text retains the original layout, new suffixed text inserts a space! 
     do 
     { 
      if (match.Success) // the text was already indexed 
      { 
       if (fileNameSuffix.Length > 0) 
       { 
        destFileName = Path.Combine(filepath, String.Format("{0}({1}){2}{3}", fileNameWOExt, (n++), fileNameSuffix, fileNameExt)); 
       } 
       else 
       { 
        destFileName = Path.Combine(filepath, String.Format("{0}({1}){2}", fileNameWOExt, (n++), fileNameExt)); 
       } 
      } 
      else // we are adding a new index 
      { 
       destFileName = Path.Combine(filepath, String.Format("{0} ({1}){2}", fileNameWOExt, (n++), fileNameExt)); 
      } 
     } 
     while (File.Exists(destFileName)); 

     File.Copy(sourceFileName, destFileName); 
    } 
Powiązane problemy