Log in Datatable speichern - Nicht immer werden alle Zellen gefüllt

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Log in Datatable speichern - Nicht immer werden alle Zellen gefüllt

    Hallo,

    ich habe ein kleines Problem. Sonst würde ich wohl auch nicht hier schreiben. :)
    Ich versuche eine LogDatei in eine Datatable zu speichern.
    Die Logdatei speichere ich in einen String und formatiere sie in eine csv um. Als Trennzeichen verwende ich #+#. Diese Zeichen kommt in keiner Konstellation vor.
    Eine Zeile sieht das zum Beispiel so aus (Etwas anonymisiert!).

    Quellcode

    1. gateway.log#+#2017-04-19#+#00:45:54,531#+#[pool-10-thread-1]#+#(de.dfgdf.blabla.xxxx.monitor.yyyyyy:294)#+#INFO#+#Loesche Monitor-Report: 2017-03-18_23-45#2017-03-19_23-45

    Einlesen machen ich dann mit so.

    VB.NET-Quellcode

    1. Public Shared dt As New DataTable("LogDatei")
    2. Public Shared Function NewLogEinlesen(LogDatei_Pfad As String, ByRef ReturnString As String) As Boolean
    3. 'Das neue Log mit dem Trennzeichen #+# wird eingelsen und gleich in das Datatable gespeichert
    4. 'LogDatei_Pfad als Logpfad der Logdatei.
    5. Try
    6. Using tfp = New Microsoft.VisualBasic.FileIO.TextFieldParser(LogDatei_Pfad, Encoding.Default)
    7. tfp.SetDelimiters("#+#")
    8. Dim fields = tfp.ReadFields
    9. While fields IsNot Nothing
    10. dt.Rows.Add(fields(0), fields(1), fields(2), fields(3), fields(4), fields(5), fields(6))
    11. fields = tfp.ReadFields
    12. End While
    13. End Using
    14. ReturnString = "Ok"
    15. NewLogEinlesen = True
    16. Catch e As Exception
    17. ReturnString = "Fehler in LogZeileZerlegen: " & e.Message
    18. NewLogEinlesen = False
    19. End Try
    20. End Function

    Es funktioniert fast immer. In einigen Zeilen fehlt das letzte Feld. In diesem Feld befindet sich die eigentliche Logmeldung. Im obigen Beispiel wäre das "Loesche Monitor-Report: 2017-03-18_23-45#2017-03-19_23-45"

    Es kommt zu keiner Fehlermeldung. Das Feld wird schlichtweg nicht gefüllt.

    Mögliche Ansätze wären Sonderzeichen oder die Länge des Strings.
    Es handelt sich meist um sehr große Meldungen in denen komplette xmls enthalten sind. Diese können schon mal 63.000 Zeichen lang sein.
    Ist das vielleicht zu groß?

    Hat jemand vielleicht eine Idee?
    @Kuechenschlacht Willkommen im Forum. :thumbup:
    Werden denn die Zeilen korrekt geschrieben?
    Passiert das in einem anderen Programm?
    Hast Du vergessen uns mitzuteilen, wie Deine DataTable formatiert ist?
    Mit 7 Strings geht das ordentlich.
    Vielleicht postest Du mal einen Logfile(-Fragment), der Deinen Effekt reproduziert.

    XML-Quellcode

    1. <?xml version="1.0" standalone="yes"?>
    2. <DocumentElement>
    3. <LogDatei>
    4. <x1>gateway.log</x1>
    5. <x2>2017-04-19</x2>
    6. <x3>00:45:54,531</x3>
    7. <x4>[pool-10-thread-1]</x4>
    8. <x5>(de.dfgdf.blabla.xxxx.monitor.yyyyyy:294)</x5>
    9. <x6>INFO</x6>
    10. <x7>Loesche Monitor-Report: 2017-03-18_23-45#2017-03-19_23-45</x7>
    11. </LogDatei>
    12. </DocumentElement>
    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!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „RodFromGermany“ ()

    Hallo @RodFromGermany. Danke für das Willkommen und die schnelle Antwort.

    Die Tabelle baue ich mit folgenden Werten auf.

    VB.NET-Quellcode

    1. 'Variablen für die Spalten setzen
    2. 'Name und Eigenschaft der Spalte
    3. Spaltenname(0) = "Logname"
    4. DataTable_aufbauen.Spaltennamen(0) = "Logname"
    5. Spalteneigenschaft(0) = Type.GetType("System.String")
    6. Spaltenname(1) = "Datum"
    7. DataTable_aufbauen.Spaltennamen(1) = "Datum"
    8. Spalteneigenschaft(1) = Type.GetType("System.DateTime")
    9. Spaltenname(2) = "Time"
    10. DataTable_aufbauen.Spaltennamen(2) = "Zeit"
    11. Spalteneigenschaft(2) = Type.GetType("System.String")
    12. Spaltenname(3) = "Meldesystem"
    13. DataTable_aufbauen.Spaltennamen(3) = "Meldesystem"
    14. Spalteneigenschaft(3) = Type.GetType("System.String")
    15. Spaltenname(4) = "Melder"
    16. DataTable_aufbauen.Spaltennamen(4) = "Melder"
    17. Spalteneigenschaft(4) = Type.GetType("System.String")
    18. Spaltenname(5) = "Meldestufe"
    19. DataTable_aufbauen.Spaltennamen(5) = "Meldestufe"
    20. Spalteneigenschaft(5) = Type.GetType("System.String")
    21. Spaltenname(6) = "Meldung"
    22. DataTable_aufbauen.Spaltennamen(6) = "Meldung"
    23. Spalteneigenschaft(6) = Type.GetType("System.String")


    Ich habe die Logdatei beigefügt. Sie wurde aber bearbeitet und anonymisiert. Effekt ist aber der gleiche. Habe noch einen Probelauf gemacht.

    Edit:
    Noch ganz vergessen.
    Ja, die Zeilen werden richtig geschrieben.
    Das Log kommt aus einer Anwendung, mit Log4J aus einem jBoss. Leider kann ich das Log nur so nehmen wie es jetzt kommt. Formatiere es aber vorher um. Entferne alle unsinnigen Zeilenumbrüche und ersetze die Trennzeichen wie " " und "-" durch ein eindeutiges Trennzeichen.
    Die erste Zeile funktioniert bei mir auch. Auch alle anderen Zeile bis auch drei. Und die ersten 6 Spalten der besagten Zeilen werden ordentlich gefüllt. Nur die letzte Spalte nicht.
    Dateien
    • Logdatei.txt

      (587,86 kB, 196 mal heruntergeladen, zuletzt: )

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

    Kuechenschlacht schrieb:

    Nur die letzte Spalte nicht.
    Auch diese beiden Zeilen werden ordentlich behandelt (dt.WriteXml(PFAD)):
    test.xml
    Und:
    Die Spalten der DataTable initialisierst Du besser so:

    VB.NET-Quellcode

    1. dt.Columns.Add("Logname", GetType(String))
    2. dt.Columns.Add("Datum", GetType(DateTime))
    3. dt.Columns.Add("Zeit", GetType(String))
    4. dt.Columns.Add("Meldesystem", GetType(String))
    5. dt.Columns.Add("Melder", GetType(String))
    6. dt.Columns.Add("Meldestufe", GetType(String))
    7. dt.Columns.Add("Meldung", GetType(String))
    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!
    Wegen der Spalten. Ich schreibe das in ein Array und habe dann eine Function zum Aufbau verwendet. Da ist auch dein Vorschlag enthalten.
    Sorry für den unvollständigen Snipsel. :)

    VB.NET-Quellcode

    1. Public Shared Function Spalten_erzeugen(Spaltenname As String, Spalteneigenschaft As Type, ByRef ReturnString As String) As Boolean
    2. 'Funktion zum erzeugen der Spalten
    3. 'Spaltennamen wird als Parameter Spaltenname übergeben.
    4. 'Spalteneigenschaft als Parameter Type. Zulässig sind folgende https://msdn.microsoft.com/de-de/library/system.data.datacolumn.datatype(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-3
    5. 'Im Fehlerfall wird die Fehlermeldung als Returnstring zurückgegeben und als Rückgabewert False
    6. Try
    7. DataTable_aufbauen.dt.Columns.Add(Spaltenname, Spalteneigenschaft)
    8. ReturnString = "OK"
    9. Spalten_erzeugen = True
    10. Catch e As Exception
    11. ReturnString = "Fehler in Spalten_erzeugen: " & e.Message
    12. Spalten_erzeugen = False
    13. End Try
    14. End Function


    Ich habe dt.WriteXml(PFAD) auch mal schnell verwendet und siehe da, er schreibt es in die XML. =O
    DANKE. :thumbsup:

    Warum wird es aber nicht angezeigt? Weder im Code mit der Schnellansicht, noch im DataGridView? Es scheint also ein Problem mit der Anzeige zu sein. :whistling:

    Frage von einem Neuling im Forum. Eher ein neues Thema schreiben, den das Anzeigeproblem würde ich schon gerne noch lösen.
    @Kuechenschlacht Lass Dir mal die Länge des Textes ausgeben.
    Spalten (DataGridViewTextBoxColumn) eines DataGridViews haben eine Property MaxInputLength, setz die mal entsprechend hoch.
    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!
    Hi.

    Ich habe das Datagridview nur mit

    VB.NET-Quellcode

    1. Me.DataGridView1.DataSource = DataTable_aufbauen.dt

    eingebunden.

    Habe es mal zusätzlich so versucht.

    VB.NET-Quellcode

    1. CType(DataGridView1.Columns("Meldung"), DataGridViewTextBoxColumn).MaxInputLength = 50000


    Leider ohne Erfolg. Zelle ist immer noch leer.
    Sollte ich vielleicht erst im DataGridView eine Tabelle aufbauen und dann das DataSource setzen?

    Edit: Offenbar steht in der Celle im DataGridView auch was drin. Habe es ausgelesen. Zeichenlänge sind 587586!!! Ganz schön groß. :huh:

    Edit2: Ich habe es nun anders gelöst. Habe ein zweites Form mit einem RichTextFeld erstellt. Bei Click auf ein Feld in der Spalte Meldung wird dieses Form angezeigt und der Inhalt der Zelle im RichTextFeld. Das funktioniert echt gut.
    Dennoch vielen Dank für die Mühe. :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Kuechenschlacht“ ()

    Nur falls es interessiert hier meine Lösung. Der Code ist aber nicht komplett von mir.

    Mousehandler initialisieren im Form Load Ereignis.

    VB.NET-Quellcode

    1. Private Sub Form1_Load(ByVal sender As Object,
    2. ByVal e As System.EventArgs) Handles MyBase.Load
    3. ' Function beim Laden des Formular Form1
    4. AddHandler DataGridView1.MouseDown, AddressOf DataGridView1_MouseDown
    5. End Sub


    Und dann die Sub zum Auswerten. Bei mir wird bei einfach Klick im DataGridView ein Sub ShowZelleMeldungInForm aufgerufen und die Zelle und Spalte übergeben. Das schreibt den Zelleninhalt in eine Variable, prüft ob das zweite Form "DataGridViewZelle" geöffnet oder geschlossen ist und führt dann entsprechende Aktionen durch.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub DataGridView1_MouseDown(ByVal sender As Object,
    2. ByVal e As MouseEventArgs)
    3. ' Mousehandler für linke Mouseklick auf DateGridView
    4. ' Die Spatlen und Zeilenwerte werden in die Variable HIT gespeichert
    5. ' Die Werten werden dann an die Sub ShowZelleMeldungInForm übergeben
    6. If e.Button = MouseButtons.Left Then
    7. Dim Hit As DataGridView.HitTestInfo = DataGridView1.HitTest(e.X, e.Y)
    8. 'Index Außerhalb der gewünschen Zeilen und Spalten abhangen.
    9. If Hit.ColumnIndex = DataGridView1.ColumnCount - 1 Then 'Letzte Spalte, da dort die Meldungen stehen
    10. If Hit.RowIndex >= 0 And Hit.RowIndex <= DataGridView1.RowCount - 1 Then
    11. 'Zweite Zeile da ansonsten die Überschriften genommen werden.
    12. 'Bis letzte Zeile
    13. Call ShowZelleMeldungInForm(Hit.RowIndex, Hit.ColumnIndex)
    14. End If
    15. End If
    16. End If
    17. End Sub
    18. Private Sub ShowZelleMeldungInForm(Zeilenindex As Integer, Spaltenindex As Integer)
    19. ' Zeigt das Form DataGridViewZelle an
    20. ' Aus der Zelle das DataGridView wird der Wert entnommen un in die Variable Zellenstring geschrieben
    21. ' Die Variable Zellenstring füllt in Form DataGridViewZelle das RichTextFeld
    22. ZellenString = Me.DataGridView1.Item(Spaltenindex, Zeilenindex).Value
    23. 'Dim Form2 As New DataGridViewZelle
    24. If FormIsLoaded("DataGridViewZelle") Then
    25. ' Form DataGridViewZelle ist geöffnet
    26. DataGridViewZelle.Close() 'erst Schließen
    27. DataGridViewZelle.Show() 'dann wieder öffnen
    28. Else
    29. ' Form DataGridViewZelle ist nicht geöffnet
    30. DataGridViewZelle.Show()
    31. End If
    32. End Sub
    33. ''' <summary>
    34. ''' Prüft, ob eine bestimmte Form bereits geladen ist
    35. ''' und gibt im Erfolgsfall True zurück
    36. ''' </summary>
    37. ''' <param name="sName">Name des Form-Objekts</param>
    38. ''' Quelle: http://www.vbarchiv.net/tipps/tipp_1766-form-bereits-geladen-net.html
    39. '''
    40. Public Function FormIsLoaded(ByVal sName As String) As Boolean
    41. Dim bResult As Boolean = False
    42. ' alle geöffneten Forms durchlauden
    43. For Each oForm As Form In Application.OpenForms
    44. If oForm.Name.ToLower = sName.ToLower Then
    45. bResult = True : Exit For
    46. End If
    47. Next
    48. Return (bResult)
    49. End Function



    Danke an @RodFromGermany für die Hilfe.
    Wer setzt das Thema eigentlich nun auch erledigt?

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

    @Kuechenschlacht Oben neben dem Titel ist ein abgerundetes Quadrat, da doppelklickst Du drauf.
    Und:
    um viel Code packst Du einen
    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!