Dateiname fortlaufend erhöhen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Xylon.

    Dateiname fortlaufend erhöhen

    Hallo alle zusammen,

    ich möchte gerne eine Datei in einem Ordner speichern via SaveFileDialog. In dem Ordner befinden sich schon Dateien, und jede neue Datei soll fortlaufend benannt werden. Die erste Datei heißt #A00000000, die zweite #A00000001 usw. Nur habe ich Probleme damit diesen Wert zu erhöhen. Ich dachte als erstes ich zähle einfach alle Dateien und addiere das irgendwie, aber das funktioniert leider nicht so gut wegen dem "#A".

    Visual Basic-Quellcode

    1. Dim counter As _
    2. System.Collections.ObjectModel.ReadOnlyCollection(Of String)
    3. counter = My.Computer.FileSystem.GetFiles(directory)
    4. Dim files = counter.Count - 1


    Aber weiter komme ich leider nicht. Blöd ist auch das ich den Namen nicht als Integer Wert behandeln kann, weil der aus den nullen eine einzige macht. Ansonsten hätte ich das dann so gemacht:

    Visual Basic-Quellcode

    1. "#A" + (00000000 + files).ToString


    Gibt es vielleicht eine bessere oder komfortablere Methode? Oder habe ich etwas übersehen?

    Danke schonmal im Voraus!
    Als erstes würde ich nicht den My-Namespace verwenden, sondern lieber die .Net Alternative.
    Und dann kommt es drauf an, wenn es autom. erstellt wird, könntest über zählen lösen, aber anders wäre es die Dateinamen auszulesen und auszuwerten und dann entsprechend den neuen Namen zu setzen.
    Ist dass # Zeichen überhaupt ein Legales Fillename Zeichen, so weit ich weiß ist es nicht möglich gewisse Zeichen in einen Dateinamen zu verwenden weswegen ich dencke dass es bei der verwendung von # zeichen zu einen Fehler beim erstellen der Datei kommt.

    LG, Herbrich
    Stimmt,

    Mann müsste dann irgendwo trotzdem ne statische variable (in einer extra Datei??) halten die den letzten höchststand speichern damit nicht wen eine datei gelöscht wird der counter wieder ein unter den höchststand geht und dann die datei mit den zur zeit höchsten wert zu überschreiben

    Filles
    1
    2
    3
    4
    5
    6
    7
    New Fille = 6

    und 6 ist nunmal 6 und keine 7, aber genau 5 würden rauskommen wen irgendwo in der mitte eine gelöscht wird. die Logic erwartet 6 Dateim, nach der Logik würde die neu erstellte Datei dann die 7te Datei. Wen jetzt aber irgendwo (egal wo) eine datei x (in diesen Fall 3) gelöscht wird dann sind noch 5 Datein vorhanden, also wird dass ganze Zahlensystem um -1 verschoben, d.h. Stadt die Datei nummer 7 zu bekommen bekommt man eine zweite Datei nummer 6. Aber dass Problem ist dass diese Datei ja schon existiert und deswegen wird 6 in schlimmstenfall überschrieben. Und je nach funktion dieser Datein kann dadurch der Programmablauf massiv empfindlich gestört werden.

    LG, Herbrich

    Xylon schrieb:

    Die erste Datei heißt #A00000000, die zweite #A00000001 usw.
    Dann zähle 0, 1, 2 und formatiere den Zähler entsprechend:

    VB.NET-Quellcode

    1. Private Number As Integer = 0
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. Dim txt = String.Format("#A{0:00000000}", Number)
    4. MessageBox.Show(txt)
    5. Number += 1
    6. End Sub

    Wenn Du morgen weiterzählen willst, leg die Variable in My.Settings an.
    @zn-gong Nö.
    Bilder
    • file.png

      2,66 kB, 144×99, 925 mal angesehen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Interessantes Thema. Hab da mal gebastelt:

    VB.NET-Quellcode

    1. Function GetNextFileName(_BaseFileName As String, _ZeroPaddingCount As Int32) As IO.FileInfo
    2. Dim InitialFileInfo As New IO.FileInfo(_BaseFileName)
    3. Dim DirectoryToSearch = InitialFileInfo.Directory
    4. Dim ValuesFound As New ArrayList
    5. For Each fiDir As IO.FileInfo In DirectoryToSearch.GetFiles(IO.Path.GetFileNameWithoutExtension(_BaseFileName) & String.Empty.PadLeft(_ZeroPaddingCount, "?"c) & InitialFileInfo.Extension)
    6. Try
    7. ValuesFound.Add(Int32.Parse(System.Text.RegularExpressions.Regex.Matches(fiDir.Name, "(?:[A-Za-z]*)(\d{" & _ZeroPaddingCount.ToString & "})")(0).Groups(1).Value()))
    8. Catch ex As ArgumentOutOfRangeException
    9. ' nix tun
    10. End Try
    11. Next
    12. ValuesFound.Sort()
    13. If ValuesFound.Count = 0 Then
    14. Return New IO.FileInfo(IO.Path.Combine(InitialFileInfo.DirectoryName, IO.Path.GetFileNameWithoutExtension(_BaseFileName) & 1.ToString.PadLeft(_ZeroPaddingCount, "0"c) & InitialFileInfo.Extension))
    15. Else
    16. Return New IO.FileInfo(IO.Path.Combine(InitialFileInfo.DirectoryName, IO.Path.GetFileNameWithoutExtension(_BaseFileName) & _
    17. (DirectCast(ValuesFound(ValuesFound.Count - 1), Int32) + 1).ToString.PadLeft(_ZeroPaddingCount, "0"c) & InitialFileInfo.Extension))
    18. End If
    19. End Function

    Damit wird die einem bestimmten Datei-Suchmuster (Parameter _BaseFileName - Dateiname incl. Pfad und Extension) entsprechende Datei, deren Dateiname (ohne Extension) mit Ziffern (der Anzahl _ZeroPaddingCount) gesucht, und ein Fileinfo mit einem Dateiname zurückgegeben, der um 1 erhöht ist, und dessen Ziffernblock nach links mit führenden Nullen aufgefüllt ist.
    Wenn es einen entsprechenden Dateinamen, der den Vorgaben entspricht, noch nicht gibt, wird ein Fileinfo zurückgegeben, dessen Dateiname auf der Ziffer 1 beruht.

    Im RegEx-Bereich bin ich nicht wirklich sicher, es gibt bestimmt eine Möglichkeit, das Try ... Catch zu umgehen, wenn die Länge der endenden Zahl im zu untersuchenden Dateinamen größer als der übergebene Parameter für die Padding-Länge ist.
    @ConnyKarras: Ich hatte das Beispiel erst aus der MSDN übernommen :whistling: :D

    @RodFromGermany: Eigentlich nehme ich ungern den My-Namespace, der counter oben war nur als temporäre Lösung gedacht :D Außerdem soll später auch eine Import-Funktion mit eingebaut werden, d.h. es ist nicht festgelegt wie die letzte Datei heißt...

    @us4711: Ist das nicht etwas zu umständlich?

    Ich habe mal überlegt, und es gäbe zur Not noch eine Lösung, die aber nicht gerade schön aussähe:

    Visual Basic-Quellcode

    1. Dim val As String
    2. If counting.ToString.Length = 1 Then
    3. val = "#A" + "0000000" + counting.ToString
    4. ElseIf counting.ToString.Length = 2 Then
    5. val = "#A" + "000000" + counting.ToString
    6. ElseIf counting.ToString.Length = 3 Then
    7. val = "#A" + "00000" + counting.ToString
    8. ElseIf counting.ToString.Length = 4 Then
    9. val = "#A" + "0000" + counting.ToString
    10. ElseIf counting.ToString.Length = 5 Then
    11. val = "#A" + "000" + counting.ToString
    12. ElseIf counting.ToString.Length = 6 Then
    13. val = "#A" + "00" + counting.ToString
    14. ElseIf counting.ToString.Length = 7 Then
    15. val = "#A" + "0" + counting.ToString
    16. End If


    Funktionieren tut sie, aber naja...Eigentlich meide ich lieber solche dicken If-Blöcke, weil es einfach zu umständlich ist immer jede Möglichkeit abzufangen und entsprechend den Wer zu ändern.
    @Xylon
    Ich kann nicht sagen, ob das umständlich ist. In jedem Fall wird die höchste Auszifferung eines Dateinamens ermittelt, die dem Suchmuster entsprich, und um eins erhöht. Und es ist eine allgemeine Lösung, die sich mit beliebigem Dateinamenaufbau anwenden lässt.
    Deine Lösung in Post#8 ist Spaghetti-Code, den ich so keinesfalls einsetzen würde.
    Das sollte funktionieren:

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Dim fileNames As New List(Of String) From {"#A00000000", "#A00000123", "#A00000444"}
    3. Dim nextFileName As String = GetNextFileName(fileNames)
    4. MessageBox.Show(nextFileName)
    5. End Sub
    6. Private Function GetNextFileName(presentNames As IEnumerable(Of String)) As String
    7. Dim highestNumber As Integer = presentNames.Select(Function(x) Integer.Parse(x.Remove(0, 2))).Max()
    8. Return "#" & (highestNumber + 1).ToString("#A00000000")
    9. End Function
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „SpaceyX“ ()

    @SpaceyX: Vielleicht sollte ich es doch noch besser erklären: Ich muss erst wissen wie die letzte Datei in dem Verzeichnis heißt, da ich später eventuell mal Dateien importiere, die dann ebenfalls fortaufend benannt werden. So weiß ich also nicht genau bei welcher Zahl wir gerade sind. Erst wenn ich weiß wie viele Dateien in dem Verzeichnis sind kann ich den neuen FileName bestimmen.

    Xylon schrieb:

    Eigentlich nehme ich ungern den My-Namespace
    Dann nimm die Ressourcen aus dem Xylon-Namespace. :thumbsup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!