for each schleife abkürzen

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von chicco84.

    for each schleife abkürzen

    hallo zusammen,

    ich hab folgendes problem: hab ein programm geschrieben, dass mehrere datendateien einlest, umwandelt und wieder abspeichert. die daten liegen für jeden tag vor, ich soll sie aber jahreweise abspeichern. um das jahr (steht als dateiname in der ursprungsdatei) herauszufinden und auch jedes einzeln abzuspeichern hab ich 2 for each-schleifen verwendet.

    VB.NET-Quellcode

    1. For Each pfade As String In My.Computer.FileSystem.GetFiles("C:\atm", FileIO.SearchOption.SearchTopLevelOnly, "*.atm")
    2. Jahr = Path.GetFileName(pfade)
    3. Jahr = Jahr.Remove(0, 8)
    4. Jahr = Jahr.Remove(4, 8)
    5. Dim sw As New StreamWriter("C:\jahresdaten\ausgabe" & CStr(Jahr) & ".txt")
    6.  
    7. 'Einen Stream aus Datei machen und Variable als String definieren
    8. For Each Dateien As String In My.Computer.FileSystem.GetFiles("C:\atm", FileIO.SearchOption.SearchTopLevelOnly, "*.atm")
    9. Dim fs As New StreamReader(Dateien)
    10. '...
    11. 'hier kommen die Befehle zum genauen auslesen einer Datei...
    12. '...
    13. next
    14. next

    jetzt hab ich allerdings das problem, dass das natürlich ewig dauert, da das jahr ja 365 tage hat, erstellt er mir meine datei für 1 jahr 365 mal neu... das ist natürlich überflüssig. ich würde noch gerne eine klausel einfügen, dass wenn das jahr dasselbe ist wie vorher, er es nicht nochmal erstellen muss.
    hat jemand eine gute idee? ich seh den wald vor lauter bäumen nicht mehr 8|
    lg
    Dann bau die Schleife andersherum auf:
    Außen den StreamWriter() für das Jahr, innen den StreamWriter() für die Tage.
    Die innere Schleife würde ich dann aber in eine Prozedur auslagern.
    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!
    danke für die tipps!

    ich hab die schleifen so angelegt, dass er bei der ersten das jahr herausfindet und innen die einzelnen tage dann bearbeitet, aber das problem ist dass das programm alle dateien immer einlest für das jahr, obwohl für ein jahr in der ersten schleife eine datei genügen würde.

    kann ich in der inneren schleife so etwas wie

    VB.NET-Quellcode

    1. if Jahr(i) = Jahr(i - 1) Then
    2. Exit For
    3. End If


    einbauen? natürlich mit deklarierung von i davor... - allerdings wie finde ich die endzahl heraus, da sich diese ja alle paar tage ändert (wenn das messgerät die daten herein schickt.)?
    Ich denke, Du willst alle Dateien, die zu einem Jahr gehören, haben. Also musst Du zumindest die Dateinamen anfassen.
    Mit

    VB.NET-Quellcode

    1. Dim path As String = "c:\Temp\"
    2. Dim files() As String = System.IO.Directory.GetFiles(path)

    hast Du alle Filenamen in einem Array und kannst sie bearbeiten, wie immer Du willst.
    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!
    Sorry, aber ich stehe heute wohl selber auf der Leitung ( vermutlich Kaffeemangel :huh: ), aber ich habe die Aufgabenstellung nicht begriffen:

    - Du hast eine Menge von Messdatendateien mit der Endung "*.atm" im Verzeichnis C:\atm\
    - diese Dateien liegen für (fast) jeden Tag des Jahres vor
    - Deine Aufgabe ist es diese Dateien jahresweise in einer einzigen Jahresdatei zusammenzufassen (???)
    - die Jahresdateien liegen im Verzeichnis C:\jahresdaten\ausgabe und haben die Endung *.txt

    Falls ich das halbwegs gecheckt habe, dann
    - werden die Messwerte einfach nur Datei für Datei hintereinandergeschrieben ?
    - sind die Dateien denn beim Einlesen auch richtig tagweise geordnet ?
    - erstellst Du jedes Mal die gesamte Jahresdatei neu, obwohl Du eigentlich nur die "neuen" drankleben müsstest ?

    Wie gesagt, bin heute nicht der Hellste ...
    also nochmal ganz genau: ^^

    ich habe daten von einem regenmesser, der jede minute aufzeichnet ob es geregnet hat und auch wieviel. diese minutenwerte (insg. 98 zeilen + eine leerzeile, danach folgt die nächste minute...) sind für jeden tag in einer datei gespeichert. aus diesen tagesdateien soll ich nun jedes regenevent mit den dazu gehörigen parametern auslesen. für jedes regenevent ist eine zeile in der neuen datei vorgesehen. hab ich also einen tag im jahr 2010 in dem es 3x geregnet hat, bekomme ich in meiner neuen datei 3 zeilen. diese ausgabe der jahresdatei ist meine "ausgabe2010.txt (oder 2009...)-datei.

    so weit so gut, das hab ich ja inzwischen schon geschafft :) das problem ist jetzt, dass ich das jahr ermitteln muss um dem streamWriter die richtige ausgabe****.txt geben zu können. das hätte ich gemacht, indem ich das jahr jeder datei über den Dateinamen herausfinde (erste for each schleife), danach lese ich alle dateien ein und überprüfe ob diese in dem selben jahr gemessen wurden und schreibe diese zeile für zeile in meine ausgabe****.txt datei. das funktioniert auch....
    jetzt habe ich aber bis zu 365 dateien für jedes jahr - also würde er die ausgabe****.txt-datei 365 mal neu erstellen....

    alles klar was ich meine?

    das möchte ich vermeiden, da es sonst ja ewigkeiten dauert bis das programm fertig ist... :sleeping:

    ich dachte, das geht vl indem ich ihm sage, dass wenn das jahr das selbe ist wie vorher, er die ausgabe****.txt-datei nicht nochmal erstellen muss... also wenn ich nun 300 dateien aus dem jahr 2010 habe, dass er diese nur einmal erstellt und dann die zweite schleife überspringt.

    lg



    EDIT:

    gibt es einen Befehl, der die anzahl der *.atm-dateien im Pfad zählen kann???

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

    VB.NET-Quellcode

    1. Dim path As String = "c:\Temp\"
    2. Dim files() As String = System.IO.Directory.GetFiles(path, "*.atm")
    3. Dim i As Integer = files.Length
    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!

    chicco84 schrieb:

    alles klar was ich meine?

    So dumm wie ich dachte war ich ja garnicht ;)

    Eigentlich sollte eine einzige Schleife ausreichen, mal als Pseudocode formuliert:
    1. alle Jahresdaten-Dateien löschen
    2. hole die erste Messdatei und extrahiere die Regenwerte
    3. öffne die entsprechende Jahresdaten-Datei mit New Streamwriter(Jahr.txt,TRUE) , dabei (siehe hier) wird der Text angehängt falls die Datei schon existiert oder neu angelegt falls nicht
    4. Daten schreiben und Streamwriter closen
    5. bei 2 mit nächster Messdaten-Datei aus der Liste weitermachen

    Auch das lässt sich optimieren wenn man sich z.B. in einer Settings-Datei merkt wie weit man letztes Mal schon gekommen war, also nur die neuen Messdaten nachträgt.

    Falls es wichtig ist, dass die Tagesdaten in der richtigen Reihenfolge geschrieben werden, muss die Dateiliste schon richtig sortiert sein oder werden. Aber das war ja bei Deinem Code auch nicht anders ...

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

    das man beim streamwriter mit "true" anhängen kann wenn es die datei schon gibt, hab ich komplett vergessen :evil: hatte ich mal gelesen, aber wohl komplett verdrängt :P

    vielen dank schon mal, ich lass gerade laufen... mal sehen obs klappt.

    noch eine frage: wieso soll ich zu beginn die datei löschen? um beim nächsten start des programms nicht alles doppelt zu bekommen?

    geordnet sind die dateien, das ist also kein problem.

    mit der settings-datei kenn ich mich nicht aus... aber vl kann ich das dann ja noch nachlesen. bewirkt das, dass es nicht immer von vorne beginnt?

    lg
    Ich würde noch folgendes Ordnungsprinzip anlegen:
    Die Dateien jedes Jahres kommen in eine separate Direktory. Die könnte glatt so heißen, wie das Jahr, :D
    die Dateinemen der Regenfiles haben Datum und Uhrzeit yyyyMMdd_hhmmss_.atm im Dateinamen, und schon ist die chronologische und die alphabetische Sortierung gleich. Der Rest ergibt sich doch nun schon fast von selbst.

    Und:
    Wieso wird alle Minute eine neue Regendatei angelegt? Die könnten doch auch zumindest täglich zu einer Datei zusammengefasst werden.

    Also:
    Des Optimierens ist kein Ende.
    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!
    auf die ausgabe-dateien des regenmessers hab ich keinen einfluss bzw zugriff... und es wird nicht für jede minute eine datei ausgegeben, die werden zu einem tag zusammengefasst, allerdings gibt es in dieser tagesdatei für jede minute 98 wertezeilen plus eine leerzeile. die haben im format ohnehin yyyyMMdd stehen. also auch auf die directory vom der ausgabe vom regenmesser hab ich leider keinen einfluss...

    trotzdem danke!

    @ kangaroo:
    vielen dank nochmal - funktioniert einwandfrei :thumbsup:

    lg

    chicco84 schrieb:

    noch eine frage: wieso soll ich zu beginn die datei löschen? um beim nächsten start des programms nicht alles doppelt zu bekommen?

    Ja genau, schliesslich arbeitest Du ja immer alle Dateien nochmal durch, und damit würdest Du die gleichen Werte ja bei jedem Durchgang nochmal in die Jahresdaten-Dateien schreiben.

    Du kannst ja mal damit experimentieren, die Namen der schon geschriebenen Dateien in einer Erledigt.txt Datei zu speichern, die kannst Du dann mbei wiederholten Durchgängen einfach überspringen, in dem Fall sollest Du das Löschen der Jahredaten allerdings weglassen. Das Schöne bei der Lösung ist, Du kannst die Erledigt.txt einfach manuell löschen und er nimmt wieder alle Messwerte neu ... wenn Erledigt.txt nicht extiert dann solltest Du allerdings das Jahres-Verzeichnis löschen ... naja, probier selber rum ...

    Wäre schön wenn Du mal schreiben würdest wie lange es vorher gedauert hat und ob es sich verbessert hat ;)
    vielen dank noch für die tipps!

    habs beim ersten mal nach ca 1 h abgebrochen, nachdem ich dann entdeckt hab wo der fehler war....
    inzwischen braucht es "nur" noch 15-20 minuten....

    ich werd mir bestimmt was überlegen, damit er nicht immer alle daten neu nimmt, da das ja jetzt schon sehr lange dauert und es ja jeden tag um 1 datei mehr wird.

    vielen dank nochmal. wenn ich noch etwas zusammen bringe bzw. hilfe brauche meld ich mich nochmal ;)

    lg
    hab inzwischen geschafft, dass er nur noch die neuen dateien einliest (mit einer Erledigt.txt und danach einer if-abfrage ob diese Datei bereits verwendet wurde) und diese dazu schreibt. allerdings kann ich noch nicht sagen wieviel zeit ich ersparnis habe, da ich ja noch auf neue dateien warten muss :P

    außerdem mach ich mit meinen jahresdaten danach noch eine berechnung in einem eigenen sub. hier lese ich die jahresdatendatei nochmals ein... hier müsste ich das auch noch hinkriegen, dass er nur neue einträge nimmt - aber so weit bin ich noch nicht gekommen...

    lg
    also mit den neuen daten geht das jetzt blitzschnell(1-5min - je nach anzahl u regenmenge) ;)

    hab aber wieder eine neue frage...
    ich habe ja eine erledigt.txt angelegt und würde aus dieser gerne die letzte Zeile löschen (da die Daten des aktuellen Tages auch schon "unvollständig" enthalten sind).

    ich dachte mir folgendes:

    VB.NET-Quellcode

    1. Dim gelesen() As String = File.ReadAllLines("C:\erledigt.txt")
    2. Dim i As Integer
    3. Dim fertig As New StreamWriter("C:\fertig.txt")
    4. Dim k As Integer
    5.  
    6. i = gelesen.Length - 1
    7. gelesen(i).Remove(0,18)
    8.  
    9.  For k = 0 To gelesen.Length - 1
    10. fertig.Write(gelesen(k) & vbCrLf)
    11. Next
    12. fertig.Close()


    allerdings sieht die fertig-datei genauso aus wie die erledigt-datei. die remove-funktion geht also nicht... WARUM??????

    lg

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

    chicco84 schrieb:

    die remove-funktion geht also nicht... WARUM??????

    Wenn Du Dir die String.Remove Methode in MSDN anschaust, so merkst Du dass es eine Function ist: sie gibt also den neuen Wert zurück. Demnach müsste es gelesen(i)=gelesen(i).Remove(0,18) heissen.

    Wenn Du nur die letzte Zeile löschen möchtest , wäre es allerdings einfacher 1 Zeile weniger zurückzuschreiben als gelesen wurden,z.B:

    VB.NET-Quellcode

    1. Dim gelesen() As String = File.ReadAllLines("C:\erledigt.txt")
    2. Dim fertig As New StreamWriter("C:\fertig.txt")
    3. ' lenght-2 (!) Zeilen zurückschreiben
    4. For i as integer=0 to gelesen.length-2
    5. fertig.writeline(gelesen(i))
    6. Next i
    7. ' Streamwriter schliessen
    8. fertig.close

    oder wenn es nur ein Ausnahmefall ist löscht Du die letzte Zeile einfach mit dem TextEditor :rolleyes:

    chicco84 schrieb:

    ch habe ja eine erledigt.txt angelegt und würde aus dieser gerne die letzte Zeile löschen (da die Daten des aktuellen Tages auch schon "unvollständig" enthalten sind).

    Verstehe ich nicht, klingt so als würden evtl doppelte Einträge geschrieben.

    Die Methode mit Erledigt.txt sollte vom PseudoCode her ungefähr so funktionieren:
    1. keine Erledigt.txt Datei da -> alle Jahresdaten löschen, alternativ kannst Du Dir hier auch nur das letzte erledigte datum merken
    2. nächste Tagesdatei ermitteln
    3. wenn Pfad schon in Erledigt.txt -> überspringen und mit 2. weitermachen, sonst weiter bei 4.
    4. Tagesdaten holen und Regenmessungen in die Jahresdatei anhängen ( New StreamWriter(pfad,TRUE) )
    5. Dateiname in Erledigt.txt aufnehmen (bzw neues erledigtes Datum eintragen)
    6. weiter bei 2

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

    ja klar, danke...

    Manchesmal bin ich einfach schon "betriebsblind" 8|

    Für heute habe ich zum Beispiel eine Datei von heute mit den Werten bis 12:55 Uhr und wenn ich das Programm nochmals durchlaufen lasse, hat er schon den Dateinamen im Erledigt.txt, aber wenn ich den letzten Eintrag immer lösche, nimmt er am nächsten Tag dann die vollständige Datei. Ansonsten fehlt mir ja der halbe Tag...

    Danke nochmal :)