DD: Warum wird die Zeile nicht ausgetauscht?

  
$fp=fopen("./_new/".$file."","a+");  
foreach ($array AS $nr => $zeile)  
	{  
	if (in_array($nr, $keys))  
		{  
	fwrite($fp,"...;\r\n");  
	        } else {  
    fwrite($fp,$zeile."\r\n");  
		}  
	}  
fclose($fp);  

Es werden (bei if==true) die neue und die alte Zeile in die Datei geschrieben.
ich wollte die zeile aber austauschen.

Dirk

  1. Tach,

    $fp=fopen("./_new/".$file."","a+");

    
    >   
    > Es werden (bei if==true) die neue und die alte Zeile in die Datei geschrieben.  
    > ich wollte die zeile aber austauschen.  
      
    du öffnest die Datei zum anhängen, also schreibst du deine Zeile nur zu dem dazu, was schon da ist.  
      
    mfg  
    Woodfighter
    
    1. du öffnest die Datei zum anhängen, also schreibst du deine Zeile nur zu dem dazu, was schon da ist.

      Hi,

      ja, aber ich öffne nur 1 x.
      Und die Datei ist ursprünglich ja leer, also kanns daran nicht liegen.
      Trotzdem danke, Dirk

  2. $fp=fopen("./_new/".$file."","a+");
    foreach ($array AS $nr => $zeile)
    {
    if (in_array($nr, $keys))
    {
    fwrite($fp,"...;\r\n");
            } else {
        fwrite($fp,$zeile."\r\n");
    }
    }
    fclose($fp);

    
    >   
    > Es werden (bei if==true) die neue und die alte Zeile in die Datei geschrieben.  
    > ich wollte die zeile aber austauschen.  
      
    Hallo  
    
    > Dirk  
      
    Dein Posting gibt Rätsel auf.  
    Ich weiß nicht, was in $array und $keys stehen soll und ob der Handler $fp auf eine noch nicht vorhandene Datei geht.  
      
    Ich nehme an, Deine alten Daten liegen in $array, die neuen sollen in die Datei, die mit dem Handler $fp vorbereitet wird, geschrieben werden. In $keys stehen die Indizes, die gelöscht werden sollen?!? Warum dann drei Punkte in die Zieldatei schreiben?  
      
    Ich würde das so machen:  
    - Datei in Array lesen (file()).  
    - Datei löschen.  
    - Mittels array\_splice Wert aus Array löschen anhand der Zeilennummer  
    - Array in Datei schreiben.  
      
    ~~~php
    $alte_daten  = file($file);  
    unlink($file);  
    array_splice($alte_daten, $del_zeile, 1);  
    // array schreiben, fopen, fputs, bla
    

    Cheers,
    Baba

    1. Dein Posting gibt Rätsel auf.

      Die Du aber alle gelöst hast. Bis auf die 3 Punkte, die ungefähr Deinem "bla" entsprechen.

      Ich würde das so machen:

      • Datei in Array lesen (file()).

      Mache ich auch.

      • Datei löschen.

      Ich schreibe in eine gänzlich neue Datei.

      • Mittels array_splice Wert aus Array löschen anhand der Zeilennummer
      • Array in Datei schreiben.

      Ist doch im Prinzip meiner Lösung recht ähnlich. Aber was ist falsch an meiner Lösung??

      Gruß, Dirk

      1. Grüße,
        was weiß denn ich, was in deinem $keys steht :=) und wie du es erstellst.
        was weiß ich, wo und wie Du die neuen Daten in $array tust. Vielleicht mit $array[] = "Neue Datenzeile"; ?!? Vielleicht mit $array[$nr] = "Neue Datenzeile"; ?!?

          
        if (in_array($nr, $keys)){  
          fwrite($fp,"...;\r\n");  
        } else {  
          fwrite($fp,$zeile."\r\n");  
        }
        

        Es werden (bei if==true) die neue und die alte Zeile in die Datei geschrieben.

        beide Bedingungen der if-Bed. können nicht wahr sein :)

        Vielleicht meinst Du ja einfach array_key_exists() stat in_array(). Ersteres sucht nach Schlüsseln, letzeres nach Werten.

        Solch ein Problem kannst Du meist sehr einfach lösen, indem Du einfach mal die Variablen mit var_dump(); ausgibst:

        var_dump($array);  
        var_dump($keys);
        

        und in der Schleife
        var_dump($nr);

        Bis später,
        Baba

        1. Grüße,
          was weiß denn ich, was in deinem $keys steht :=) und wie du es erstellst.
          was weiß ich, wo und wie Du die neuen Daten in $array tust. Vielleicht mit $array[] = "Neue Datenzeile"; ?!? Vielleicht mit $array[$nr] = "Neue Datenzeile"; ?!?

          Hi Baba,

          ersteres. Aber dennoch ist ein guter Hinweis in Deiner Frage. Ich sollte 2.re Methode wählen.

          if (in_array($nr, $keys)){
            fwrite($fp,"...;\r\n");
          } else {
            fwrite($fp,$zeile."\r\n");
          }

          
          >   
          > > Es werden (bei if==true) die neue und die alte Zeile in die Datei geschrieben.  
          >   
          > beide Bedingungen der if-Bed. können nicht wahr sein :)  
          >   
            
            
          Das stimmt nicht. Da $nr ein String ist und $keys ein ganz normales eindimensionales Array, wird ein String in den Values gesucht, dafür ist in\_array durchaus zuständig.  
            
            
          
          > Solch ein Problem kannst Du meist sehr einfach lösen, indem Du einfach mal die Variablen mit var\_dump(); ausgibst:  
          >   
            
            
          Ich finde die var\_dump-Anzeige (noch) verwirrender als print\_r(). Aber recht hast du schon.  
            
            
          Erstmal dank, Dirk
          
  3. moin,

    von Deiner Frage mal abgesehen, bei Sowas gehe ich anders heran: Datei auf ein Array lesen, mit dem Array operieren und das Array zurück in die Datei schreiben, fertig.

    Hotti

    1. moin,

      von Deiner Frage mal abgesehen, bei Sowas gehe ich anders heran: Datei auf ein Array lesen, mit dem Array operieren und das Array zurück in die Datei schreiben, fertig.

      Hi Hotti,

      habe ich auch gemacht, es ändert nichts. Meine Zeile wurde nicht ausgetauscht.

      Dirk

      1. Hello Dirk,

        habe ich auch gemacht, es ändert nichts. Meine Zeile wurde nicht ausgetauscht.

        lass uns doch mal vorne anfangen, dann können wir Dir bestimmt besser helfen.

        Die Aktion, die Du da durchführst, nennt sich "Mischen von Daten / mischen von Dateien", falls Du mal in klassischen Lehrbüchern danach suchen willst.

        Du müsstet mal den gesamten relevanten Code liefern.

        Der Code besteht beim Mischen immer aus der Beschreibung von (mindesntes) zwei Quellen und (mindestens) eines Zieles. Du solltest uns also genau beschreiben, was in den beiden Datenquellen drinsteht, wie es dort hinein kommt und wie Du gedenkst, sie zu synchronisieren bzw. nach welchem Kriterium Du das Mischen vornimmst. Bei Dir ist das augenscheinlich der Key. Der muss dazu aber in beiden Quellen im selben Format vorliegen.

        Also bitte nochmal von vorne.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Bei Dir ist das augenscheinlich der Key. Der muss dazu aber in beiden Quellen im selben Format vorliegen.

          Hallo Tom,

          ja, der Key. Und ich glaube auch fast, dass es daran liegt, dass der Key nicht in beiden Fällen identisch ist.

          Es deucht mir, dass eventuell die falsche Zeile ausgetauscht wird, was ich damit gleich setze, dass eine Zeile hinzugefügt wird.

          Bevor ich weitere Fragen stelle, muss ich das erstmal selber genauer erroieren.

          Bis hierher danke, Dirk

          1. Bevor ich weitere Fragen stelle, muss ich das erstmal selber genauer erroieren.

            Hallo,

            das habe ich nun gemacht.

            Ergebnis ist folgendes:

            Ich habe eine datei, eingelesen in ein Array $datei2, wobei

            --> im Key die Zeilennummer und
            --> im value der Zeileninhalt

            steht.

            Dann habe ich ein weiteres, mehrdimensionales Array $ersatz, welches

            --> im Key die zu ersetzende Zeilenummer enthält und
            --> im value ein Array, das
                 --> im Key die Originalzeile enthält und
                 --> im value die neue zeile.

            Beispiel für $ersatz:

            Array
            (
                [259] => Array
                    (
                        [originalzeile1] => ersatzzeile1
                    )

            [332] => Array
                    (
                        [originalzeile2] => ersatzzeile2
                    )

            [364] => Array
                    (
                        [originalzeile3] => ersatzzeile3
                    )

            [388] => Array
                    (
                        [originalzeile4] => ersatzzeile4
                    )
            )

            Trotzdem schaffe ich es seit ein paar tagen nicht, in der Datei für die entsprechenden Zeilen die Ersatzzeile einzusetzen.

            Hier bitte ich dann Euch um Hilfe. Nicht funktionierenden Code kann ich Euch inzwischen seitenweise anbieten. Vielleicht schenke ich mir das aber auch besser und es zeigt mir jemand, wie es zu lösen ist?

            Gruß, Dirk

            1. Hello Dirk,

              Ergebnis ist folgendes:

              Ich habe eine datei, eingelesen in ein Array $datei2, wobei

              --> im Key die Zeilennummer und
              --> im value der Zeileninhalt

              steht.

              Dann habe ich ein weiteres, mehrdimensionales Array $ersatz, welches

              --> im Key die zu ersetzende Zeilenummer enthält und
              --> im value ein Array, das
                   --> im Key die Originalzeile enthält und
                   --> im value die neue zeile.

              Beispiel für $ersatz:

              Array
              (
                  [259] => Array
                      (
                          [originalzeile1] => ersatzzeile1
                      )

              [332] => Array
                      (
                          [originalzeile2] => ersatzzeile2
                      )

              [364] => Array
                      (
                          [originalzeile3] => ersatzzeile3
                      )

              [388] => Array
                      (
                          [originalzeile4] => ersatzzeile4
                      )
              )

              Trotzdem schaffe ich es seit ein paar tagen nicht, in der Datei für die entsprechenden Zeilen die Ersatzzeile einzusetzen.

              Da scheint noch ein Designfehler vorzuliegen.

              Entscheide Dich, über welches Kriterum (eineindeutigen Schlüssel) Du den Austausch vornehmen willst. Beschreibe doch mal mit einfachen deutschen Worten, so wie eine 80jährige Buchhalterin, die noch nie einen "Kompjuter" gesehen hat, das Problem mit ihren Karteikästen lösen würde...

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
              1. Da scheint noch ein Designfehler vorzuliegen.

                Hi Tom,

                Das ist nicht ganz fair. Denn diese Aussage ist aehnlich kokret wie "funktioniert nicht" und ich kann keinen Bezug nehmen.

                Entscheide Dich, über welches Kriterum (eineindeutigen Schlüssel) Du den Austausch vornehmen willst.

                Die Zeilennummer ist eindeutig. Ich weiss, dass es nach Designfehler riecht, weil ich den originalen Zeilentext nochmal "mitparsen"  moechte. Das ruehrt daher, dass ich noch zwei, drei Infos aus dem Text dieser Zeile benoetige. Klar haette ich die auch bereits vorher ziehen koennen, aber an dieser Stelle passte mir besser.

                Grüße, Dirk

                Tom vom Berg

            2. Hallo,

              Du bist sehr undeutlich in dem was du konkret machst. Ich glaube dich verwirrt auch was in PHP eine meiner nach sehr schlechte Designentscheidung war dass man Array und Dictionary von der Syntax her vermischt hat. Du versuchst dich in einem Assoziativen Array (wo anders Dictionary genannt), bei dem ich nicht weiß woher du die Keys nimmst und das dann grundsätzlich so aussieht dass da immer Paare von key-value drin sind:

              $d = array("key" => "value", "key2" => "value2");  
              echo $d["key2"]  
              // -> value2
              

              Was man in deinem Fall eigentlich machen sollte, so weit ich deine Beschreibung verstanden habe, ist ein ganz normales Array (kein Assoziatives), also eine Liste von items nimmt die keine Paare hat sondern wo numerische Keys automatisch generiert werden:

              $a = array("value", "value2");  
              echo $a[1]; // Nummerierung fängt bei 0 an, deshalb schreiben wir 1 um das zweite item aus dem Array zu bekommen  
              // -> value2
              

              Grundsätzlich würde das was du versuchst zu machen, aleo eine Zeile in einer Datei ersetzen, so funktionieren:

              $overwrite_line = 3;  
              $new_string = "my new text";  
              $file_path = "myfile.txt";  
                
              $file_array = file($file_path); // Datei in ein Array einlesen, jede Zeile ist ein item im Array  
              if(count($file_array) > $overwrite_line) { // ersetze nur wenn es die Zeile auch gibt  
                  $file_array[$overwrite_line - 1] = "my new text" . "\n"; // ersetze die Zeile (die nummerierung fängt bei 0 an, deshalb das -1  
                  file_put_contents($file_path, $file_array); // Schreibe das veränderte Array zurück in die Datei  
              }
              

              Jeena

              1. Hallo,

                . Du versuchst dich in einem Assoziativen Array (wo anders Dictionary genannt), bei dem ich nicht weiß woher du die Keys nimmst

                Ich lasse mi eine Vorschlagliste der zu ersetzenden Zeilen generieren und jede Zeile ist ein inputfield, dass als key bereits die zeilennummer, als 2.-key (sozusagen) die Originalzeile und als Value die Ersatzzeile enthaelt.

                Na h Abwenden dieses Formulars bin ich dort, wo ich jetzt grad stehe.

                Grüße, Dirk

                1. Hello,

                  . Du versuchst dich in einem Assoziativen Array (wo anders Dictionary genannt), bei dem ich nicht weiß woher du die Keys nimmst

                  Ich lasse mi eine Vorschlagliste der zu ersetzenden Zeilen generieren und jede Zeile ist ein inputfield, dass als key bereits die zeilennummer, als 2.-key (sozusagen) die Originalzeile und als Value die Ersatzzeile enthaelt.

                  Na h Abwenden dieses Formulars bin ich dort, wo ich jetzt grad stehe.

                  Das ist zwar kompliziert, aber Du wirst schon wissen, warum Du das so machst.
                  Ich vermute mal, dass die Whitespaces (Begriff in Google nachsuchen) dich dabei stören. Beim Einlesen der Daten aus der Datei wirst Du die vermutlich mit abspeichern und in der Darstellung der Vorschlagsliste (in HTML?) gehen die dann verloren.

                  Die assoziativen Keys können daher vermutlich nicht gleich sein.

                  Darum schrieb ich ja sinngemäß, dass das Konzept vergurkt sei.

                  Du kannst das Ganze nur untersuchen, indem Du Dir eine sinnvolle Debugansicht der Daten (Keys) bastelst, in der die Whitespaces nicht mehr verloren gehen. Meisten (insbesondere bei HTML-Darstellung) bleibt einem da nur eine Umwandlung der Zeichen in Hex-Codes, die man sich dann anzeigen lässt.

                  Es wäre mMn hier sinnlos, Dir jetzt eine schnelle Lösung zu posten. Mehr hilft Dir vermutlich eine Anleitung zum Debuggen solcher Probleme, oder? Die kannst Du dann nämlich immer wieder verwenden!

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bergpost.annerschbarrich.de
    2. Hallo,

      von Deiner Frage mal abgesehen, bei Sowas gehe ich anders heran: Datei auf ein Array lesen, mit dem Array operieren und das Array zurück in die Datei schreiben, fertig.

      Das ist zwar jetzt ein bisschen off topic, aber man bekommt mit dieser Methode Probleme wenn die Datei größer ist als der zur Verfügung stehende Speicher. Eigentlich würde es ausreichen die Datei aufzumachen, den Dateizeiger dann zu der Zeile zu bewegen die man ändern möchte dann eine Zeile schreiben (die dann die Zeile die schon drinn ist  überschreibe) und den file handler wieder zu schließen. Das müsste auch viel viel schneller gehen als alles in den Speicher zu schreiben und dann komplett wieder alles auf die Festplatte.

      Ich war mal bei einem Google Interview Workshop an meiner Uni, da hatten sie uns eine ähnliche Aufgabe gestellt.

      Jeena

      1. Tach!

        Datei auf ein Array lesen, mit dem Array operieren und das Array zurück in die Datei schreiben, fertig.
        Das ist zwar jetzt ein bisschen off topic, aber man bekommt mit dieser Methode Probleme wenn die Datei größer ist als der zur Verfügung stehende Speicher.

        Richtig, aber solch große Dateien bearbeitet man eher selten in Web-Requests. Man kann durchaus erstmal davon ausgehen, dass die Array-Methode ausreichend ist.

        Eigentlich würde es ausreichen die Datei aufzumachen, den Dateizeiger dann zu der Zeile zu bewegen die man ändern möchte dann eine Zeile schreiben (die dann die Zeile die schon drinn ist  überschreibe) und den file handler wieder zu schließen.

        Eine Textdatei ist keine Datenbank. Dein Vorschlag funktioniert nur dann, wenn der neue Text exakt die gleiche Länge hat, wie der alte. Ansonsten hast du einen Textrest stehen gelassen oder den nachfolgenden Text überschrieben.

        Das müsste auch viel viel schneller gehen als alles in den Speicher zu schreiben und dann komplett wieder alles auf die Festplatte.

        Ab der zu ändernden Stelle ist der Rest neu zu schreiben. Das geht innerhalb einer Datei, wenn der neue Text kleiner ist und man den nachfolgenden Text nach vorn kopieren kann. Für größeren Text braucht es zwei Puffer. Der eine enthält den einzufügenden Teil, in den zweiten kommt vorher das was im Weg steht. So hangelt man sich bis zum Ende. Alternativ eine zweite Datei schreiben, da hat man weniger logischen Aufwand. Der zeitliche Unterschied ist abhängig vom ersten unveränderten Teil.

        dedlfix.

        1. Hallo,

          Richtig, aber solch große Dateien bearbeitet man eher selten in Web-Requests. Man kann durchaus erstmal davon ausgehen, dass die Array-Methode ausreichend ist.

          Jo, deshalb "off topic". (Übrigens steht nirgendwo dass das über einen Web-Request abgehandelt wird.)

          Eine Textdatei ist keine Datenbank. Dein Vorschlag funktioniert nur dann, wenn der neue Text exakt die gleiche Länge hat, wie der alte. Ansonsten hast du einen Textrest stehen gelassen oder den nachfolgenden Text überschrieben.

          Stimmt das habe ich nicht richtig durchdacht.

          Ab der zu ändernden Stelle ist der Rest neu zu schreiben. Das geht innerhalb einer Datei, wenn der neue Text kleiner ist und man den nachfolgenden Text nach vorn kopieren kann. Für größeren Text braucht es zwei Puffer. Der eine enthält den einzufügenden Teil, in den zweiten kommt vorher das was im Weg steht. So hangelt man sich bis zum Ende. Alternativ eine zweite Datei schreiben, da hat man weniger logischen Aufwand. Der zeitliche Unterschied ist abhängig vom ersten unveränderten Teil.

          (Off topic) bei Problemen mit dem Speicher ist das aber durchaus sinnvoll so zu machen, weil man dann immer nur einen kleinen Bereich der Datei im Speicher halten muss.

          Jeena

      2. hi,

        von Deiner Frage mal abgesehen, bei Sowas gehe ich anders heran: Datei auf ein Array lesen, mit dem Array operieren und das Array zurück in die Datei schreiben, fertig.
        Das ist zwar jetzt ein bisschen off topic, aber man bekommt mit dieser Methode Probleme wenn die Datei größer ist als der zur Verfügung stehende Speicher.

        Ja, sehr OT, ist das: Solch eine Datei würde ich weder mit PHP noch mit Perl bearbeiten, da würde ich höchstens mal nachfragen, wie die Datei auf das System gekommen ist ;)

        Hotti

        1. Hallo,

          Ja, sehr OT, ist das: Solch eine Datei würde ich weder mit PHP noch mit Perl bearbeiten, da würde ich höchstens mal nachfragen, wie die Datei auf das System gekommen ist ;)

          Ach so Abwegig finde ich das gar nicht, man muss sich ja nur das Forumsarchiv mit 3,4 GB angucken und damit was machen wollen, schon passt es nicht in den Hauptspeicher.

          Jeena

          1. hi,

            Ja, sehr OT, ist das: Solch eine Datei würde ich weder mit PHP noch mit Perl bearbeiten, da würde ich höchstens mal nachfragen, wie die Datei auf das System gekommen ist ;)
            Ach so Abwegig finde ich das gar nicht, man muss sich ja nur das Forumsarchiv mit 3,4 GB angucken und damit was machen wollen, schon passt es nicht in den Hauptspeicher.

            Es kommt immer auf die konkrete Aufgabenstellung an. Dateien jenseits 3 GB habe ich auch mit Perl noch nicht bearbeitet, es würde sehr wahrscheinlich auch länger als 10 min dauern, den Inhalt in den Hauptspeicher zu lesen, wo dann das OS auch auslagern wird.

            Gute Erfahrungen habe ich damit gemacht, Dateien (XML, CSV) bis 300 MB komplett in den Hauptspeicher zu lesen auf eine mir passende Datenstruktur, ggf. entwerfe ich dazu den Algorithmus selbst, sofern es kein passendes CPAN Modul gibt, was mir die Arbeit erleichtern kann. Wenn der ALgorithmus passt, ist der Rest dann nur noch Tipparbeit ;)

            Beim Durchsuchen von Text-Dateien hingegen gehen meine Scripts zeilenweise durch die Datei, ohne den kompletten Inhalt in den RAM zu lesen. Das Suchergebnis allerdings kommt dann in den Hauptspeicher, wo es für die Ausgabe aufgearbeitet wird, z.B. wird hier ein Array-Slice nach dem Codepoint sortiert für die Ausgabe; das funktioniert auch mit PHP-Array's einwandfrei.

            Viele Grüße,
            Hotti