Textdatei zeilenweise einlesen, dann SPLITTEN funktioniert nicht: System.IndexOutOfRangeException: "Index was outside the bounds of the array."

  • VB.NET
  • .NET 5–6

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von gume1970.

    Textdatei zeilenweise einlesen, dann SPLITTEN funktioniert nicht: System.IndexOutOfRangeException: "Index was outside the bounds of the array."

    Hallo,

    ich nutze Steam und schreibe dennoch ein kleines Programm, das meine liebsten Spiele direkt startet. Im grunde ganz einfach: Ein Klick führt einfach die ausführbare Datei im Steamordner aus. (Diese startet dann Steam, etc aber das Spiel läuft)
    Dazu habe ich eine kleine Textdatei, die wie folgt aussieht: "GAMESLIST.txt"
    Spiel1,Spiel1Pfad,SPiel1Exe,SPiel1Kategorie
    Spiel2,Spiel2Pfad,SPiel2Exe,SPiel2Kategorie
    Spiel3,Spiel3Pfad,SPiel3Exe,SPiel3Kategorie
    und so weiter.

    Nun das problem:

    FOLGENDES FUNKTIONIERT

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim ZEILE As String
    3. Dim TEMP1, TEMP2, TEMP3, TEMP4 As String
    4. Dim UMWANDEL() As String
    5. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6. ZEILE = "GameTitel,GamePfad,GameExe,GameKat"
    7. ' Dim str2() As String = Split(ZEILE, ",")
    8. UMWANDEL = Split(ZEILE, ",")
    9. TEMP1 = UMWANDEL(0)
    10. TEMP2 = UMWANDEL(1)
    11. TEMP3 = UMWANDEL(2)
    12. TEMP4 = UMWANDEL(3)
    13. Label1.Text = TEMP1 + "=" + TEMP2 + "=" + TEMP3 + "=" + TEMP4
    14. End Sub
    15. End Class

    ALSO GANZ EINFACH MEIN ERSTES TESTPROGRAMM

    Und jetzt in meinem eigentlichen Programm folgendes:

    VB.NET-Quellcode

    1. Dim ZEILE As String
    2. Dim UMWANDEL() As String
    3. Dim TEMP1, TEMP2, TEMP3, TEMP4 As String
    4. Private Sub SPIELE_EINLESEN()
    5. If My.Computer.FileSystem.FileExists(STARTPFAD + "\GAMESLIST.txt") Then
    6. Dim objReader As New System.IO.StreamReader(STARTPFAD + "\GAMESLIST.txt")
    7. Do
    8. ZEILE = objReader.ReadLine()
    9. If Not ZEILE Is Nothing Then
    10. UMWANDEL = Split(ZEILE, ",")
    11. TEMP1 = UMWANDEL(0)
    12. TEMP2 = UMWANDEL(1)
    13. TEMP3 = UMWANDEL(2)
    14. TEMP4 = UMWANDEL(3)
    15. End If
    16. Loop Until ZEILE Is Nothing
    17. objReader.Close()
    18. Else
    19. MsgBox(STARTPFAD + "\GAMESLIST.txt missing!")
    20. End If
    21. End Sub



    Ich erhalte bei der Ausführung "System.IndexOutOfRangeException: "Index was outside the bounds of the array." und als alter Mann steige ich nicht hinter das Problem.
    PS: STARTFAD stimmt, die Datei ist vorhanden und wird auch gelesen. Aber bei dem Versuch dann die ZEILE zu spiltten, der mir nicht erklärbare Fehler

    Hilfe bitte....

    CodeTags gesetzt ~VaporiZed

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

    Wenn du alter Mann 1970 geboren wurdest, bist du immer noch 11 Jahre jünger als ich.
    Dein Code ist unleserlich, dafür gibt es hier oben über dem Feld schöne Tags, VB.Net wäre angemessen.

    Ich habe deinen Code hergenommen und in ein Testprojekt geschmissen, habe mir die Gameslist.txt erstellt und den Startpfad entsprechend ergänzt.
    Ich habe keinen Aufruf der Sub SPIELE_EINLESEN() festgestellt!
    Aber, wenn ich den hier gezeigten Code ausführe, dann erhalte ich keinen(!) Fehler. Meine Textdatei wird ebenfalls ausgelesen und ich habe die Routine um eine Debug.Print Ausgabe erweitert um das zu verifizieren.

    Also wo konkret knallt es bei dir und wie genau sieht die Fehlermeldung aus?
    Hallo. WOW, erst einmal VIELEN Dank für Deine Mühe und Betrachtung. Also...

    Hmmm. Wenn ich die Routine ausführen lasse im Programm,
    erhalte ich die Fehlermedung: System.IndexOutOfRangeException: "Index was outside the bounds of the array."
    Genau hinter "TEMP2 = UMWANDEL(1)". TEMP1 = UMWANDEL(0) funktioniert

    Mein Problem: Ich möchte eine Textliste einlesen, immer vier Felder einer Zeile, durch Kommata getrennt (SPIELNAME,SPIELPFAD.SPIELEXE,KATHEGORIE).
    Dies bitte Zeile für Zeile, also nacheinander. Nach dem Einlesen der Zeile, soll eben jene in die vier Bestandteile geteilt werden.
    "Split" soll dies übernehmen "," ist das Trennzeichen.
    Danach sollen TEMP1 eben SPIELNAMEN, TEMP2 den SPIELPFAD usw. erhalten.
    Und diese Temp weise ich dann durch einen Zähler (+1 je Zeile) diversen Arrays zu ( Dim GAMETITEL(500) As String
    Dim GAMEPFAD(500) As String, Dim GAMEEXE(500) As String, Dim GAMEKAT(500) As String).




    Aber so weit komme ich gar nicht. Mir gelingt durch Split nicht die Teilung. Programm bricht genau mit der obigen Meldung an der Stelle ab. Ich kann weder zuweisen, noch ausgelesene Inhalte verarbeiten.


    Ohne, dass mir ersichtlich ist, warum...

    Mein gesamtes Programmkonstrukt funktioniert, wenn ich diese Inhalte als Daten im Quellcode zuweise. Ich möchte dies aber durch eine Textliste verwalten lassen,
    um diese schnell ändern zu können (Spielname ändert sich, neues Update, andere Kategorie, etc). Die Pfade zu STeam lasse ich zu Beginn erkennen. Das alles funktioniert,
    ebenso die Verwaltung durch / mit Cover oder durch Klick starten. AUch Spiele aus diesem Originlauncher kann ich so ganz einfach einbinden. Das soll also alle Spiele
    für mich unter einem Dach ganz simpel vereinen, ohne dass ich durch Launcher, Startprogramme, Oberflächen wühlen muss.


    Ich habe schnell manuell Daten einiger STEAM Spiele als Test eingebaut. Oberfläche und Co werden sich noch ändern. Mit meinem Programm kann ich also meine
    Steamsammlung starten aber auch meine Onlinespiele wie "Elite Dangerous", "Guild Wars II", ohne die in Bibliotheken aufnehmen zu müssen. Wie aber auch Tools
    (Datenträgerverwaltung, Uninstaller, Wallpaperwechsler). Also eine Art Schaltzentrale für SPiele und Programme. Wobei die Steamspiele natürlich Steam laden aber
    das soll ja auch so sein und funktioniert reibungslos.


    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „gume1970“ ()

    Ich hatte geschrieben, dass ich dein Programm ohne Fehler durchlaufen habe.
    Ich habe mir erlaubt nur deine Beispieldaten zu nehmen, das heißt, wenn die Annahme stimmt, dass deine Zeile 3 Kommas enthält, dann würde UMWANDELN auch 4 Elemente (0 bis 3) enthalten.
    Dein Fehler liegt also in deiner Datei und zwar genau in der aktuellen Zeile. Probier mal den folgenden Code im Debug-Modus.
    Die Ausgabe erfolgt im Ausgabe Fenster

    VB.NET-Quellcode

    1. Private Sub SPIELE_EINLESEN()
    2. If System.IO.File.Exists(STARTPFAD + "\GAMESLIST.txt") Then
    3. Dim objReader As New System.IO.StreamReader(STARTPFAD + "\GAMESLIST.txt")
    4. Dim cnt As Integer = 0
    5. Do
    6. ZEILE = objReader.ReadLine()
    7. cnt = cnt + 1
    8. If Not ZEILE Is Nothing Then
    9. UMWANDEL = Split(ZEILE, ",")
    10. If UMWANDEL.Count < 4 Then
    11. MessageBox.Show($"Zeile {cnt} hat nicht geügend Felder.")
    12. Else
    13. Debug.Print($"{UMWANDEL(0)}={UMWANDEL(1)}={UMWANDEL(2)}={UMWANDEL(3)}")
    14. End If
    15. End If
    16. Loop Until ZEILE Is Nothing
    17. objReader.Close()
    18. Else
    19. MessageBox.Show(STARTPFAD + "\GAMESLIST.txt missing!")
    20. End If
    21. End Sub

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

    Ich gehe davon aus, dass deine Input-Datei nicht deiner definierten Norm entspricht.
    Da gibt's bestimmt Zeilen, die keine 3 Kommas beinhalten (vielleicht eine Leerzeile?).
    Edit: OK, wurde im Vorpost schon erwähnt.

    Notiz am Rande:
    Wenn du tatsächlich in .Net programmierst, solltest du nicht VB6-Stil verwenden.
    Dein Programm lässt sich sicher als Fünfzeiler schreiben.
    Ansatz: ​For Each Line In System.IO.File.ReadAllLines(...)
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

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

    petaod schrieb:

    Ansatz: ​For Each Line In System.IO.File.ReadAllLines(...)
    Dann besser For Each Line In System.IO.File.ReadLines(...)
    docs.microsoft.com/de-de/dotne…readalllines?view=net-6.0
    docs.microsoft.com/de-de/dotne…le.readlines?view=net-6.0
    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!
    WOW.

    Ich bin... wirklich überwältigt von Euren Mühen!

    Aktuell gerade unterwegs, werde ich das Ganze nachher testen. Das eine Zeile weniger als vier Felder enthält, habe ich im generieren schon ausgeschlossenm. AAAAABER: Wer weiss, ob es da hängt...
    Da muss ich ran!

    Schnell in der Pause an den rechner... textliste schnell auf nur zehn Einträge gekürzt...

    LÄUFT!

    GENAU DAS WAR ES. Obwohl mein Testprogramm die Datei sauber erstellt (liest die Pfade aus, schreibt die Datei), muss irgendwo etwas mit den Kommata haken! Ich habs durch das obige Beispiel gerade schnell festgestell.


    WAS IST DAS PEINLICH! ;)

    RodFromGermany schrieb:

    Dann besser ReadLines(...)
    Da musste ich doch tatsächlich mal den Unterschied nachlesen.

    Microsoft schrieb:

    ​The ReadLines and ReadAllLines methods differ as follows: When you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient.
    Im konkreten Fall dürfte es keinen Unterschied machen, aber generell scheint wohl ReadLines die bessere Methode zu sein.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Ich finde das weitgehend Geschmacksache, was von beiden schneller ist kommt wohl eher auf die HW an. Selbst bei tausenden von Zeilen habe ich kaum Zeitdifferenzen nachgewisen, spürbar waren die jedenfalls nicht.
    Allerdings habe ich auch nur modernste HW im Einsatz, mit schnellen SSDs. Bei lahmen Festplatten wäre das Einlesen in einem Zug (ReadAllLines) vermutlich schneller und auch gesünder für die Festplatte.

    Dksksm schrieb:

    Ich finde das weitgehend Geschmacksache,
    ReadAllLines hält alle Zeilen vor, während ReadLines die nächste Zeile raus pickt.
    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!
    Ich nutze hier auch Top Gaming Hardware. Und ja, auch die schnelleren SSD. Festplatten meachnischher Art aber noch sehr viel als externe für meine Fotografie. So gut zwanzig 4TB dürften hier stehen.

    Für meine bescheidenen Versuche hier, die kleine Datei mit vielleicht maximal 70 Zeilen Inhalt und auf SSD und SuperÜber Gamingboliden, dürfte die Herangehensweise relativ unwichtig sein. Was ich bemerke,
    ist die Handhabung von z.B. den Gamecovern, die einheitlich als "COVER.PNG" mit größerer Größe in dem Hauptverzeichnis eines SPiels habe. 38 Cover passen auf eine Seite meiner kleinen Lösung,
    beim Blättern und suchen (also prüfen der Pfade, einlesen der Cover, zuweisen in PIctureBoxen) spüre ich etwas Verzögerung. Mechanische Platten wären da sicher noch langsamer.

    PS: Ich habe VisualBasic bewusst gewählt, weil ich damit kleine STartumgebungen für meine Emulationsumgebungen erstellt habe (Cover, Reviewsverwaltung, SPielstarten) und dies auf jeden
    meiner alten Emulationsrechner (und älteren Notebooks) läuft. VB scheint da weiterhin anspruchslos, dass ich einfach dabei geblieben bin.

    DANKE EUCH für die HILFE! Ich RIND bin auf diese Ursache NULL gekommen! ;)

    Ihr seid Klasse, wirklich!

    Dksksm schrieb:

    Das weiß ich
    Bei ellenlangen Dateien kommt da doch etwas die Performance ins Spiel.
    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!
    Hallo,

    ich hatte mir das zuvor angeschaut. Bisher habe stets nur "readlines" oder "writelines" verwendet. In Nutzung habe ich damit stets nur kleine Konfigurationsdateien zu den Startern
    geschrieben, in denen vielleicht vier, fünf Informationen standen. Oder in DosBox die Ergänzungs-Konfigurationen der SPiele gelesen (max 10 Zeilen)

    Bei so einer kleiner Anzahl, halte ich sogar das CFGFULLSCREEN = fw.ReadLine, DUNKLERMODUS = fw.ReadLine (Beispiel) für übersichtlicher,
    als alles auszulesen und dann umzuwandeln.

    Bisher also nur bescheidene Anwendungsfälle. Ich komme gar nicht in Eure Sphären, 22 GB Text einzulesen ;) (Spaß, aber Ihr versteht)