Laden...

.txt filtern die eine Bedingung erfüllt und die Ergebnisse in eine neue .txt schreiben

Erstellt von hardy0166 vor 5 Jahren Letzter Beitrag vor 5 Jahren 2.822 Views
H
hardy0166 Themenstarter:in
3 Beiträge seit 2018
vor 5 Jahren
.txt filtern die eine Bedingung erfüllt und die Ergebnisse in eine neue .txt schreiben

Hallo ich bin blutiger Anfänger und habe folgendes Problem.

In meinen Logfiles erscheint der Text - "mit Fehlern abgelehnt <0>" was bedeutet das keine Fehler aufgetreten sind. Ich müsste nun alle Zeilen haben deren Wert >0 ist. Wie ist dies zu lösen? Ich bin bisher nur so weit gekommen, dass ich mir die anzeigen lasse deren Wert 1 ist. Siehe unten

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1WinKashLog2
{
    class Program
    {
        static void Main(string[] args)
        {
            int counter = 0;
            string line;

            // Read the file and display it line by line.  
            System.IO.StreamReader file =
                new System.IO.StreamReader(@"C:\Logfiles2\Protokolldateien\Log_20180606.log");
            while ((line = file.ReadLine()) != null)
            {
                if (line.Contains("mit Fehlern abgelehnt <1>") == true)
                    System.Console.WriteLine(line);
                counter++;
            }

            file.Close();
            System.Console.WriteLine("There were {0} lines.", counter);
            // Suspend the screen.  
            System.Console.ReadLine();
        }
    }
}

Danke für die Hilfe im Vorraus.

Enrico

Hinweis von Abt vor 5 Jahren

Auch als blutiger Anfänger möge man sich bitte an [Hinweis] Wie poste ich richtig? halten und die Code Tags verwenden.

1.040 Beiträge seit 2007
vor 5 Jahren

Du kannst mit

if (!line.Contains("mit Fehlern abgelehnt <0>"))

alle Zeilen ausgeben, die nicht 0 als Fehleranzahl haben.
Entscheidend ist dabei das Ausrufezeichen, dass die Bedingung negiert.

Generelle Tipps:

H
hardy0166 Themenstarter:in
3 Beiträge seit 2018
vor 5 Jahren

Danke für die schnelle Antwort. Es klappt so nicht. Bei - if (!line.Contains(mit Fehlern abgelehnt <0>)) - Wird die kompl. Datei mit allen Werten Zeile für Zeile ausgeben.

1.040 Beiträge seit 2007
vor 5 Jahren

Dann probiere die Zeile mal mit 1 aus. Dann solltest du ja alle Einträge bekommen, die ungleich 1 sind.

Ansonsten zeige mal bitte einen Teil der Datei.

Tipp 3: [Artikel] Debugger: Wie verwende ich den von Visual Studio?

T
2.219 Beiträge seit 2008
vor 5 Jahren

Oder im Bestfall so:


if (line.Contains("mit Fehlern abgelehnt") && !line.Contains("<0>"))

Somit prüfst du erst ob der Text "mit Fehlern abgelehnt" vorkommt und dass eben "<0>" nicht vorkommt.

Somit solltest du alles was einen Fehler hat aber eben nicht 0 ist abfangen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

H
hardy0166 Themenstarter:in
3 Beiträge seit 2018
vor 5 Jahren

Eine Zeile der Datei ist so aufgebaut

06.06.2018 11:20:17: Belegimport: Mandant <1234034>: Batchlauf fehlerfrei beendet, Anzahl Belege <12>, fehlerfrei übernommen <12>, mit Fehlern abgelehnt <0>

der Text "mit Fehlern abgelehnt" wird nicht beachtet sondern nur die Zahlen werden ausgewertet.

16.806 Beiträge seit 2008
vor 5 Jahren

Ich würde einfach über jede Zeile iterieren und mit Hilfe von Regex ( [Artikel] Regex-Tutorial ) die Informationen raus ziehen.
Das ist im Endeffekt programmatisch leichter und sicherer - man braucht halt die Regex Pattern.

Ansonsten nimm bitte die Hinweise der Helfer entgegen und verwende den Debugger.


var lines= File.ReadAllLines(@"C:\Logfiles2\Protokolldateien\Log_20180606.log");
foreach(var line in lines)
{
   if(inhalte wie gewünscht)
   {
        // mach was..
        System.Console.WriteLine(line);
   }
}

Und wozu mit StreamReader arbeiten wenn das Framework das einem schon alles schenkt...

T
2.219 Beiträge seit 2008
vor 5 Jahren

Die while schleife in der aktuellen Form ist auch nicht ganz sinnvoll.
Frage lieber ab ob EndOfStream des StreamReader false ist und lies dann die Zeile in der Schleife.
Diese C/C++ Variante finde ich in C# sehr unschön und macht den Code nicht lesbarer!

Ebenfalls soltlest du die StreamReader Instanz nicht file nennen, dass ist iritierend.
Nimm lieber reader als Variablenname, dann ist klar womit du dort arbeitest.

Nachtrag:
Und nutzt using um den StreamReader, da du ihn nur schließt aber kein Dispose aufrufst.
Da der StreamReader auch unmanged Resourcen hält, muss er diese freigeben, was er so nicht macht.


public static void Main(string[] args)
{
	int counter = 0;
    
    using(StreamReader reader = new StreamReader(@"C:\Logfiles2\Protokolldateien\Log_20180606.log"))
	{
		while (!reader.EndOfStream)
        {
			string line = reader.ReadLine();

			if (line.Contains("mit Fehlern abgelehnt"))
				Console.WriteLine(line);
			
            counter++;
		}
    }
	
    Console.WriteLine("There were {0} lines.", counter);
	Console.ReadLine();
}

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

M
368 Beiträge seit 2006
vor 5 Jahren

Neben C# kann man auch Grep (Version f. Windows) verwenden: https://www.techrepublic.com/article/10-ways-to-use-grep-to-search-files-in-linux/

Goalkicker.com // DNC Magazine for .NET Developers // .NET Blogs zum Folgen
Software is like cathedrals: first we build them, then we pray 😉

16.806 Beiträge seit 2008
vor 5 Jahren

Und nutzt using um den StreamReader, da du ihn nur schließt aber kein Dispose aufrufst.

Auch wenn using() natürlich die bessere Variante ist: Close ruft natürlich Dispose auf..

T
2.219 Beiträge seit 2008
vor 5 Jahren

@Abt
Stimmt, ist sogar die einzige Funktion in Close.
Nutze nur nch die using Variante, weshalb mir das Detail entfallen ist.
Dein Code mit File.ReadAllLines würde ich nur mit vorsicht empfehlen, da wir nicht wissen wie fett die Logs sind.
Wenn diese 1-2 GB oder gar noch größer sind, knallt es wegen der Menge an Zeilen schon weg.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor 5 Jahren

Dein Code mit File.ReadAllLines würde ich nur mit vorsicht empfehlen, da wir nicht wissen wie fett die Logs sind.

KISS-Prinzip

Man macht es dann "komplexer", wenn es notwendig ist.
Mit "aber wir wissen doch gar nicht" und "ich will alles erschlagen!" hat man noch nie eine gute (=> stabile) Software entwickelt 😉

Die Menge an Zeilen ist i.d.R. irrelevant; vorher knallts i.d.R. am Speicherlimit.
Darüber hinaus gibt es überhaupt keine Notwendigkeit auf EndOfStream zu prüfen 😉


    using(StreamReader reader = new StreamReader(@"C:\Logfiles2\Protokolldateien\Log_20180606.log"))
    {
        string line;
        while ((line = sr.ReadLine()) != null) 
        {
            // code..
        }
    }

Einfacherer und stabiler.
Man muss nur wissen, wie die Dinge hinter der Fassade funktionieren.

T
2.219 Beiträge seit 2008
vor 5 Jahren

@Abt
Das Speicherlimit Problem meinte ich ja mit der Anzahl an Zeilen.
Klar ist es so einfacher, aber mit dem StreamReader eben bei größeren Logs eben Speicherschonender.

Ich halte EndOfStream als Prüfung für sinnvoller, da diese die gleichen Absicherungen hat wie ReadLine auf null zu prüfen.
Und es ist aus meiner Sicht auch lesbarer und klarer versätndlich.
Sind aber eher kleine Details über die man in diesem Fall streiten kann.

Warum der Code dadurch stabiler sein soll ist mir aber nicht ganz klar.
Da File.ReadAllLines auch nur intern den StreamReader nutzt und alles in eine Liste schiebt um es dann als Array zu liefern, ist hier aus meiner Sicht kein Vorteil an Stabilität gegeben.
Würde man hier umständlich mit irgendwelchem magischen Code arbeiten, würde ich dir zustimmen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor 5 Jahren

a) Dein EoL wird damit doppelt geprüft; wird in ReadLine bereits gemacht -> unnötig
b) Ein (Is)Null(OrEmpty)-Prüfung musst Du so oder so machen, willst Du kein potentiell unstabilen Code.

T
2.219 Beiträge seit 2008
vor 5 Jahren

@Abt
a) Stimmt, wäre aber kein großes Problem und macht den Code aus meiner Sicht lesbarer.
Spielt also für mich in dem Szenario keine Rolle und stört auch kaum die Performance.
Aber wenn du vergleiche hättest ob dadurch die Performance großartig sinkt, dann würde ich das nochmal überdenken.

b) Die Null Prüfung der Zeile ist nur nötig, wenn eben auf EndOfStream true wäre beim Aufruf von ReadLine. Sonst gibt es immer einen String selbst wenn dieser leer wäre. Wenn dieser leer ist, wäre dies in diesem Fall egal, da dann eben das Contains oder ein RegEx keinen Treffer hätte und der Code ohne Prüfung laufen würde.
Man kann dann zwar die Prüfung überspringen, halte ich aber in diesem simplen Fall schon für Micro Optimierung und somit vernachlässigbar.
Stabiler wird der Code durch die Prüfung kaum.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

49.485 Beiträge seit 2005
vor 5 Jahren

Hallo T-Virus,

ich sehe es wie Abt: Bei Dateioperationen sollte man es vermeiden, Prüfung und Zugriff(sversuch) zu trennen.

Das klassische Beispiel ist eine Prüfung auf File.Exists und danach ein (ungesichertes) File.Open. Das File.Open kann aber trotz des erfolgreichen File.Exists fehlschlagen (aus diversen Gründen, aber eben auch), weil die Datei in der (zugegen extrem kurzen, aber eben doch vorhandenen) Zwischenzeit gelöscht worden sein könnte. Man muss eben immer damit rechnen, dass parallel andere Prozesse den geprüften Zustand verändern.

Und im konkreten Fall könnte (passendes FileShare für die beiden hierbei beteiligten Prozesse mal vorausgesetzt) die Datei bei der Prüfung auf EndOfStream noch größer sein, als beim Zugriff durch ReadLine, weshalb ReadLine trotz zuvor noch nicht erreichtem EndOfStream dann doch null liefert. Auch wieder sehr, sehr unwahrscheinlich, aber eben doch möglich.

Daher ist meine Empfehlung die gleiche, wie die von Abt: ReadLine auf null testen und die Prüfung auf EndOfStream weglassen bzw. gar nicht erst einbauen.

herbivore