bestimmte Zeile einer csv finden und löschen

Ich habe deinen Code nicht von Anfang bis Ende analysiert aber hier:
Code:
$monat = date("d.m.Y", strtotime("-3 month"));
sehe ich, dass Du Tag.Monat.Jahr für das Format des Datums verwendest, ebenso in der CSV-Datei, die Du angehängt hast. Damit funktioniert ein Vergleich nicht, Du musst das umgekehrte Format Jahr.Monat.Tag verwenden.
Oder alternativ kannst Du das Ganze objektorientiert aufziehen und DateTime und die Funktion diff verwenden.
 
Ich habe deinen Code nicht von Anfang bis Ende analysiert aber hier:
Code:
$monat = date("d.m.Y", strtotime("-3 month"));
sehe ich, dass Du Tag.Monat.Jahr für das Format des Datums verwendest, ebenso in der CSV-Datei, die Du angehängt hast. Damit funktioniert ein Vergleich nicht, Du musst das umgekehrte Format Jahr.Monat.Tag verwenden.
Oder alternativ kannst Du das Ganze objektorientiert aufziehen und DateTime und die Funktion diff verwenden.
das Datum ist eigentlich nicht das Problem

ich hab nochmal Änderungen vorgenommen

ich erhalte jetzt über die echo-ausgabe die gewünschen Zeilen, nur das zurückspeichern in eine csv funktioniert nicht richtig

aber vielleicht habe ich generell den falschen Ansatz?

PHP:
<?php
error_reporting(0);

ini_set('memory_limit', '1024M'); // or you could use 1G

// CSV auslesen---------------------------------------------------------------------------------------------------------------------
function csvToArray($csvFile){
    $file_to_read = fopen($csvFile, 'r');
    while (!feof($file_to_read) ) {
        $lines[] = fgetcsv($file_to_read, 1000, ';');
    }
    fclose($file_to_read);
    return $lines;
}
//read the csv file into an array
$csvFile = 'HK40Log - Kopie.csv';
$csv = csvToArray($csvFile);

//render the array with print_r
//echo '<pre>';
//print_r($csv[0]);
//echo '</pre>';

$tempfile = 'temptest.csv';

$monat = date("d.m.Y", strtotime("-3 month"));

echo "Datum ab dem zur&uuml;ck gesucht wird: " . $monat;

$suchstring = strtotime($monat);

$aarray=array('0', '3'); //Werte die bleiben, 0 = volle Stunde, 3 = halbe Stunde

$il = 0;

foreach($csv as $subArray){

    $lines = $subArray[0] . ' Line ' . $il . ' bleibt<br>';

    $subArray[0] = utf8_decode($subArray[0]);
    $subArray[0] = str_replace('?', '', $subArray[0]);

    $substring = substr($subArray[0], 0, 10);

    $substring = strtotime($substring);
    
    if($substring < $suchstring){
        //echo '<p>' . $subArray[0] . '</p>';
        //echo '<p>' . substr($subArray[0], 14, 2) . '</p>';
        $a = substr($subArray[0], 14, 1);
        if (!in_array($a,$aarray)){
            //echo '<p>' . $subArray[0] . '</p>';
        }else {
            
            $i = 0;
            
            while ($i < 169) {
                $line = $line . $csv[$il][$i] . ";";
                $i = $i + 1;
            }
            
            echo '<p>' . $lines . '</p>';
            
        }
        
    }
    
    if($substring > $suchstring){
        $i = 0;
            
        while ($i < 169) {
            $line = $line . $csv[$il][$i] . ";";
            $i = $i + 1;
        }
            
        echo '<p>' . $lines . '</p>';
        
    }
    
    $temp = file_get_contents($tempfile,"r");

    $file = fopen($tempfile, 'w+');
    
    fwrite($file, chr(239) . chr(187) . chr(191) . $line . "\n" . $temp);
    
    $il = $il + 1;
}

fclose ($file);

?>
 
Ich habe jetzt mit deinem Code eine Testdatei angelegt und das echo durch var_dump ersetzt, um auch die Zeilennummer zu sehen. Wenn ich das mit deiner originalen CSV-Datei laufen lasse, bekomme ich nur die Ausgaben aus Zeile 77:
Code:
        var_dump($lines);
aber nichts von Zeile 63. Woraus ich schließe, dass die Bedingung
Code:
if ($substring < $suchstring)
nie erfüllt ist. Und das wiederum führe ich auf das Format der beiden Strings mit dem Datum zurück, die verglichen werden.
 
PS: Davon abgesehen würde ich das noch anders aufziehen:
Ich gehe davon aus, dass die Datenmenge relativ groß ist, daher würde ich darauf verzichten, die Zeilen in einem Array zwischen zu speichern sondern sie gleich beim Einlesen mit fgetcsv zu verarbeiten. Um nicht unnötig Arbeitsspeicher zu belegen.
Der Vergleich mit '0' und '3' ist unflexibel. Ich würde auch hier einen Vergleich machen, ob das Intervall seit dem letzten Speicher größer als 30 oder 60 Minuten oder ... ist, dann brauchst Du das Intervall nur in einer Variablen zu definieren.
Und es mit DateTime aufziehen.
 
es sind aktuell über 57000 Zeilen

das war eben mein Lösungsansatz

Datenzeilen die älter als 3 Monate sind, sollen ausgedünnt werden. Es wird alle 10min eine Datenzeile erstellt, was aber nicht zu geraden Zeiten wie 10:30 oder 11:00 passiert. Sondern im Abstand von 10min ab Startzeit die auch 11:36 sein kann.

zum Beispiel: 11:36, 11:46, 11:56 (und wenn der Server zwischendurch neu startet) gehts mit 12:13, 12:23 usw. ....

Darum vergleiche ich das Datum was älter als 3 Monate sein soll und die Minuten zur vollen halben oder ganzen Stunde --> 24.04.2024 12:05

Stimmen die vergleich überein soll die ganze Zeile in eine neue csv geschrieben werden. und natürlich auch alle Zeilen die jünger als 3 Monate sind.

Aktuell werden zwar die gewünschten Zeilen in eine csv geschrieben, doch leider ohne Zeilenumbruch

Ich hoffe ich konnte es verständlich erklären was ich möchte.

Ich bin mir sicher das ganze geht einfacher oder kürzer. Aber bevor ich optimieren kann muss es mal laufen.
 
Zuletzt bearbeitet:
Ich denke schon, dass ich den Aufbau der Datei, wie sie überarbeitet werden soll und deinen Ansatz verstehe.
Aktuell werden zwar die gewünschten Zeilen in eine csv geschrieben, doch leider ohne Zeilenumbruch
Hast Du das wirklich über einen Zeitraum von mehr als 3 Monaten getestet? Ich bin immer noch der Meinung, dass ein String-Vergleich bei einem Format Tag.Monat.Jahr nicht funktionieren kann.
 
Du schriebst zwar, dass Du nur einen Denkanstoß willst, aber weil ich es eine interessante Aufgabe fand, habe ich es mit DateTime mal durchgezogen:
Code:
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);

ini_set('memory_limit', '1024M'); // or you could use 1G

// CSV auslesen---------------------------------------------------------------------------------------------------------------------
// Intervall zwischen den Zeiten wenn ausgedünnt wird in Minuten:
$intvBetween = 30;
// Intervall in die Vergangenheit wo ausgedünnt werden soll
// in Tagen:
$intvBefore = 90;

$csvFile = 'HK40Log.csv';
$destFile = 'HK40Log-filtered.csv';
$now = new DateTime();
var_dump($now);
$lastWritten = new DateTime();
$file_to_read = fopen($csvFile, 'r');
$file_to_write = fopen($destFile, 'w+');
while (!feof($file_to_read)) {
    $line = fgetcsv($file_to_read, 1000, ';');
    // Damit der folgende Code fehlerfrei funktioniert
    // muss die Zeile erfolgreich geparst sein:
    if ($line !== false) {
        // Um von der genauen Position von Datum und Zeit unabhängig zu sein,
        // benutzen wir eine Regex:
        preg_match('/\d\d\.\d\d\.\d{4} \d\d:\d\d:\d\d/', $line[0], $matches);
        var_dump($matches);
        $currentTime = DateTime::createFromFormat('d.m.Y G:i:s', $matches[0]);
        $diffBefore = $currentTime->diff($now);
        var_dump($diffBefore->days);
        if ($diffBefore->days > $intvBefore) {
            var_dump('line is older than $intvBefore days');
            // Die Zeile ist älter als $intvBefore,
            // prüfen ob das Intervall zwischen zwei Ausgaben
            // schon abgelaufen ist:
            $diffBetween = $currentTime->diff($lastWritten);
            var_dump($diffBetween->days);
            if ($diffBetween->i + $diffBetween->h * 60 > $intvBetween) {
                var_dump('$intvBetween exeeded, write it');
                $lastWritten = DateTime::createFromFormat('d.m.Y G:i:s', $matches[0]);
                fputcsv($file_to_write, $line, ';');
            }
        } else {
            var_dump('line is younger than $intvBefore days, write uncond.');
            // Die Zeile ist jünger als $intvBefore,
            // wir schreiben sie direkt in die Zieldatei:
            fputcsv($file_to_write, $line, ';');
        }
    }
}
fclose($file_to_read);
fclose($file_to_write);
Ich habe zum einfachen Testen eine Datei mit einigen jungen und einigen mehr als 90 Tage alten Einträgen genommen, siehe Anhang, und das Ergebnis ist wie ich es erwarte.
 

Anhänge

Guten Morgen

ich habe deinen Code mal über die ganze Liste laufen lassen. Dazu kamen folgende Fehler

Notice: Undefined offset: 0 in C:\Web\Apache24\htdocs\csvlog\del-test3.php on line 31

Fatal error
: Uncaught Error: Call to a member function diff() on bool in C:\Web\Apache24\htdocs\csvlog\del-test3.php:32 Stack trace: #0 {main} thrown in C:\Web\Apache24\htdocs\csvlog\del-test3.php on line 32


und weiter schreibt er vor das Datum Sonderzeichen --> 
bzw. im Editor steht das Datum und Uhrzeit in Anführunszeichen --> "26.07.2024 10:18:04"
Diese stören bei der Weiterverarbeitung durch Grafana

Die Daten wurden aber reduziert, ob es die richtigen waren hab ich noch nicht kontrolliert

:unsure:
 
Zuletzt bearbeitet:
Guten Morgen zurück,
ich hatte meinen Fokus auf die Zeitvergleiche und das Ausdünnen gelegt und die Sonderzeichen erst Mal nicht beachtet. Ich hatte ja die Datei geändert und mein Editor hatte es mit BOM gespeichert. Nachdem ich es neu ohne BOM gespeichert habe, waren die Sonderzeichen verschwunden. Aber nachdem ich es zurück geändert hatte auf mit BOM tauchten sie ebenfalls nicht mehr auf.
Erste Maßnahme: Den Fall abfangen, dass Datum und Uhrzeit nicht erfolgreich geparst werden konnten, Zeilen 32 und 57.
Zweite Maßnahme: Eine Zeilennummer führen, um die Zeile in der CSV-Datei ausfindig machen zu können, wo ein Fehler auftritt.
Code:
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);

ini_set('memory_limit', '1024M'); // or you could use 1G

// CSV auslesen---------------------------------------------------------------------------------------------------------------------
// Intervall zwischen den Zeiten wenn ausgedünnt wird in Minuten:
$intvBetween = 30;
// Intervall in die Vergangenheit wo ausgedünnt werden soll
// in Tagen:
$intvBefore = 90;

$csvFile = 'HK40Log.csv';
$destFile = 'HK40Log-filtered.csv';
$now = new DateTime();
var_dump($now);
$lastWritten = new DateTime();
$file_to_read = fopen($csvFile, 'r');
$file_to_write = fopen($destFile, 'w+');
$lineNr = 1;
while (!feof($file_to_read)) {
    echo "Zeile $lineNr<br>";
    $line = fgetcsv($file_to_read, 1000, ';');
    // Damit der folgende Code fehlerfrei funktioniert
    // muss die Zeile erfolgreich geparst sein:
    if ($line !== false) {
        // Um von der genauen Position von Datum und Zeit unabhängig zu sein,
        // benutzen wir eine Regex:
        preg_match('/\d\d\.\d\d\.\d{4} \d\d:\d\d:\d\d/', $line[0], $matches);
        // Den Fall abfangen, dass dieses Format nicht gefunden wurde:
        if (isset($matches[0])) {
            var_dump($matches);
            $currentTime = DateTime::createFromFormat('d.m.Y G:i:s', $matches[0]);
            $diffBefore = $currentTime->diff($now);
            var_dump($diffBefore->days);
            if ($diffBefore->days > $intvBefore) {
                var_dump('line is older than $intvBefore days');
                // Die Zeile ist älter als $intvBefore,
                // prüfen ob das Intervall zwischen zwei Ausgaben
                // schon abgelaufen ist:
                $diffBetween = $currentTime->diff($lastWritten);
                var_dump($diffBetween->days);
                if ($diffBetween->i + $diffBetween->h * 60 > $intvBetween) {
                    var_dump('$intvBetween exeeded, write it');
                    $lastWritten = DateTime::createFromFormat('d.m.Y G:i:s', $matches[0]);
                    fputcsv($file_to_write, $line, ';');
                }
            } else {
                var_dump('line is younger than $intvBefore days, write uncond.');
                // Die Zeile ist jünger als $intvBefore,
                // wir schreiben sie direkt in die Zieldatei:
                fputcsv($file_to_write, $line, ';');
            }

        } else {
            echo 'Fehler beim Parsen von "' . $line[0] . '"<br>';
        }
    }
    $lineNr++;
}
fclose($file_to_read);
fclose($file_to_write);
 
Zurück