Bestimmte Zeile aus csv ändern


common

Mitglied
Hallo zusammen,

ich bräuchte bitte eure Hilfe.

Ich habe ein PHP script erstellt mit dem ich als sozusagen Webinterface meine Funksteckdosen im Haus über ein Raspi steuere.

Ich würde gerne in einer .csv den aktuellen Status mitschreiben, derzeit sind zwei Dosen angeschlossen und ich würde gerne in zeile 1 den Status von Dose 1 und in Zeile 2 den Status von Dose 2 loggen.

Status ist immer 1 oder 0

Mein Problem ist ich scheitere leider am Schreiben in die Datei, hier mal mein Script, das funktioniert aber nicht da ich immer Neue Zeilen erstelle.

Es wird einfach nicht sauber nur der Wert geändert sonder auch eine neue Zeile eingefügt, und wenn ich das EOL weg lasse dann steht alles in der gleichen Zeile. :(

Kann mir jemand helfen wie ich das schreiben muss damit immer nur die Betroffene Zeile überschreiben wird?

Danke

PHP:
    //Datei in der der Status steht
    $statusfile = "status.csv";
    //Neuer Status der geschieben werden soll
    $statusneu = (int)$com;
    //Zeile in der der alte Status steht,Devicenummer = Zeilennummer, Stauts von Dose 2 Steht in Zeile 2
    $devicestatusline = (int)$device;
   
    $lines = file($statusfile);
    $lines[$devicestatusline-1] = $statusneu;
   
    $datei = fopen($statusfile,'w') ;
    foreach($lines as $value)
    {
        fwrite($datei, $value . PHP_EOL);
    }
    fclose($datei);
ich danke euch!
 
Zuletzt bearbeitet:

basti1012

Erfahrenes Mitglied
Kannst du mal den Inhalt der Datei posten und makieren welche daten da genau geändert werden soll ?

Wenn deine Datei so aussehen sollte
Code:
dose=0
dose=0
Würde ich es so versuchen
PHP:
<?php

$statusfile = "status.txt";
$dose[]=1;//neuer wert dose 1
$dose[]=2;// neuer wert dose 2 

if(file_exists($statusfile)){
     if(is_writable($statusfile)){

         $lines = file($statusfile);
         $datei = fopen($statusfile,'w') ;
         foreach($lines as $num => $key) {
               $status=explode('=',$key);
               $status[1]=$dose[$num];
               $neu=implode('=',$status);
               fwrite($datei, $neu .PHP_EOL);
         } 
         fclose ($datei);
    }else{
         echo "Datei nicht beschreibbar";
    }
}else{
    echo " Datei existiert nicht";
}
?>
Das ist meine Idee.
Wenn einer bessere Ideen hat oder was zu bemängeln hat möchte ich das auch gerne wissen weil ich auch noch dazu lernen möchte
 
Zuletzt bearbeitet:

common

Mitglied
Inhalt ist bei zwei Dosen zb.
Code:
1
0
In Zeile 0 steht der Wert von Dose 1 und in Zeile zwei der Wert von Dose 2


Vielen Dank für deine Hilfe!!!
 

basti1012

Erfahrenes Mitglied
Ja dann kann man das explode und implode auch weg lassen.
Theoretisch auch die Schleife ( wenn man den Code leicht ändert )
 

common

Mitglied
Danke Basti,
aber sind wir dann nicht eigentlich wieder bei meinem Code?

Ich seh nicht was du meinst?

Es ist so, zur Steuerung gebe ich beim Shell_exec das Device mit, das ist ein Numerischer Werrt der einfach sagt welche Dose angesprochen werden soll, diesen hole ich mit $_GET und schreib den in den Wert
$devicestatusline, dann hab ich mir gedacht das die zeile in der CSV immer die gleiche sein muss wie der Wert dann weis ich immer automatisch welche Zeile geändert werden muss.
 

ComFreek

Mod | @comfreek
Moderator
if(file_exists($statusfile)){
if(is_writable($statusfile)) {
Im Allgemeinen würde ich solche Prüfungen vermeiden. Sie haben nämlich keinen wirklich Mehrwert als Fehlermeldungen direkt von den Dateiöffnenoperationen (file, fopen) abzufangen. Im Gegenteil: sie garantieren nicht, dass Letztere erfolgreich sind: Zum einen, weil es noch mehr Prüfungen geben müsste (etwa is_readable), die du praktisch gesehen nie alle hinschreiben kannst. (Warum auch? Das OS machtes doch für dich sowieso beim Öffnen.) Zum anderen, können durch Race Conditions nach dem Prüfen (d.h. nach dem zweiten { oben) die Bedingungen wieder invalidiert werden (externes Löschen der Datei) und du bist wieder am Anfang.
 

basti1012

Erfahrenes Mitglied
Im Allgemeinen würde ich solche Prüfungen vermeiden. Sie haben nämlich keinen wirklich Mehrwert als Fehlermeldungen direkt von den Dateiöffnenoperationen (file, fopen) abzufangen. Im Gegenteil: sie garantieren nicht, dass Letztere erfolgreich sind: Zum einen, weil es noch mehr Prüfungen geben müsste (etwa is_readable), die du praktisch gesehen nie alle hinschreiben kannst. (Warum auch? Das OS machtes doch für dich sowieso beim Öffnen.) Zum anderen, können durch Race Conditions nach dem Prüfen (d.h. nach dem zweiten { oben) die Bedingungen wieder invalidiert werden (externes Löschen der Datei) und du bist wieder am Anfang.
Danke für die Info.
hat sich erledigt, war ganz einfach zu lösen!
Wie hast du es jetzt gemacht ?


Ich seh nicht was du meinst?
Ohne implode und explode und Schleife meinte ich es so
PHP:
$statusfile = "status.csv";
$dose1=1;//neuer wert dose 1
$dose2=2;// neuer wert dose 2 

$lines = file($statusfile);
$datei = fopen($statusfile,'w') ;
$lines[0]=$dose1;
$lines[1]=$dose2;
fwrite($datei, $lines[0] .PHP_EOL);
fwrite($datei, $lines[1] .PHP_EOL);
fclose ($datei);
Bei 2 Zeilen hätte ich jetzt gedacht das man es auch so machen kann.
Wenn es mehr sind dann natürlich Schleife.

Was meinen den die Profis dazu ?
 

ComFreek

Mod | @comfreek
Moderator
  • Fehlerprüfungen fehlen, mindestens für file und fopen
  • Race Condition, wenn nach file() jemand anderes die Datei beschreibt, dann gehen seine Änderungen verloren.
  • Minor nitpick: Mich nerven Programme, die auf Windows meine absichtlich gewählten Unix-style Line-Endings (LF) gegen CR-LF tauschen, nur weil sie intern sowas wie PHP_EOL nutzen :)
    Das kann man aber nicht so einfach beheben - da müsste man heuritisch feststellen, was denn das intendierte Zeilenende ist.
Als Lösung für den zweiten Punkt würde ich fopen($statusfile, 'x+') empfehlen - zumindest sieht das nach einem guten Blick auf die PHP-Doku nach dem aus, was man hier möchte: öffne die Datei exklusiv zum Lesen und Schreiben. Wobei: das schlägt fehl, wenn die Datei schon existiert. Das wollen wir natürlich nicht.
Anscheinend soll man fopen(..., "r+") und flock(..., LOCK_EX) nutzen, siehe PHP: flock - Manual und das Beispiel dort.
 

ComFreek

Mod | @comfreek
Moderator
Ich erinnere mich dunkel, dass ich solch einen Code erst kürzlich hier gepostet hätte. Muss ich später mal suchen!
 

common

Mitglied
Falls es euch interessiert so schauts jetzt bei mir aus,ich beschreibe immer Zeile 1 und Zeile 2 in 0 steht nur ne Erklärung.

Funktioniert!

Code:
$array = file($statusfile); 
array_splice($array, $devicestatusline, 1, $statusneu . "\n"); // wenn kein zeilen umbruch \n geht es nicht
$string = implode("", $array);
file_put_contents($statusfile, $string);
 

Neue Beiträge