Bionicman: Zeilenumbruch in txt-Datei 1 oder 2 Byte lang?

Hallo,

Wie man dem Titel schon entnehmen kann, wüsste ich gerne wie lang ein Zeilenumbruch in einer Textdatei ist.

Das Problem ist folgendes. Ich habe ein kleines Script, das aus einer .txt-Datei ein zweidimensionales Array erstellt. Kann man sich vorstellen wie einen Level in einem Iso-Spiel.

Das Script sieht so aus:

  
$g_fields = array();  
$handle = @fopen("fields.txt", "r");  
	  
if($handle)  
{  
	for( $y=0; $y<28; $y++ )  
	{  
		for( $x=0; $x<28; $x++ )  
		{  
			$g_fields[$y][$x] = fread($handle, 1);  
		}  
		fseek($handle, 1, SEEK_CUR);  
	}  
	fclose($handle);  
}  

Wichtig ist hier die 1 in fseek. Sprich am Zeilenende, nach 28 Zeichen, setze ich den Filepointer auf die nächste Zeile.

ABER:

Offline muss ich hier 2 einfügen, sprich den Zeiger 2 Bytes vorsetzen. Aber online bei 1und1 muss ich wie im Script 1 nehmen.

Kann mir vielleicht Jemand erklären wieso?

Danke und Gruß,
Olli

  1. Hi,

    Wie man dem Titel schon entnehmen kann, wüsste ich gerne wie lang ein Zeilenumbruch in einer Textdatei ist.

    die Antwort darauf ist: "Je nachdem".
    Mit PHP hat das jedenfalls nichts zu tun - Zeilenumbrüche werden je nach System unterschiedlich dargestellt:

    \r (Carriage Return, 0x0D)
    Auf älteren MacOS-Versionen, auf vielen zu-nix-kompatiblen Kleincomputern der 80er und 90er Jahre

    \n (Line Feed, 0x0A)
    Auf Unix-basierten Systemen

    \r\n (Carriage Return plus Line Feed, 0x0D 0x0A)
    Auf DOS und Windows

    Iso-Spiel

    Was ist ein ISO-Spiel?

    So long,
     Martin

    --
    Niemand ist überflüssig: Er kann immer noch als schlechtes Beispiel dienen.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  2. Hi,

    Wichtig ist hier die 1 in fseek. Sprich am Zeilenende, nach 28 Zeichen, setze ich den Filepointer auf die nächste Zeile.

    Warum so kompliziert?

    Kennst du file nicht?
    Kennst du parse_ini_file nicht?
    Kennst du nicht die Möglichkeiten, direkt ein Array als PHP-Code auszugeben und abzuspeichern, so dass du es nur noch per include einbinden müsstest?

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
  3. Hello Olli,

    Wie man dem Titel schon entnehmen kann, wüsste ich gerne wie lang ein Zeilenumbruch in einer Textdatei ist.

    Das hängt davon ab, wie Du ihn selber fetlegst.
    Der Begriff "Textdatei" ist dabei allerdings in gewisser Weise gewachsen und "geschützt". Er klassifiziert in den unterschiedlichen Betriebssystem- und Filesystemwelten Dateien, die nur vorwärts lesbar sind und bei denen man nur jeweils am Ende etwas anfügen kann. Das stammt immer noch aus der Welt der Bandanlagen.

    Beim Übergang zu den DO-Systemen (Festplattenorientierte Systeme)

    • hat die Microsoftwelt sich dann für ein 0x0D 0x0A entschieden,
        also die Codes #13 und #10, entsprechend ihrer Bedeutung Carriage Return (CR),
        Linefeed (LF)
    • hat die Unixwelt sich für ein einzelnes 0x0A, also den Bytecode #10 mit der
        Bedeutung Linefeed (LF) entschieden
    • Die Mac-Welt bis zur Umstellung auf BDS-Linux im Background hat nur das 0x0D, also #13 benutzt.

    PHP kennt allerdings gar keine reinen Textdateien mehr, sondern nur noch Dateien mit wahlfreiem Zugriff. Man kann zwar auch hier noch Dateien mit dem Öffnungsmodus 'a' (Append) öffnen, was einen dann daran hindert, mitten in die Datei hineinzuschreiben, aber zum Lesen kannst Du darin navigieren.

    Dein Problem scheint aber vermutlich durch die Übertragung der Datei von einem System zum anderen per FTP zu stammen. Du hast vermutlich nicht den Binärmodus, sondern den sogenannten "ASCII-Modus" benutzt. Hier werden die Dateien dann beim Hochladen verändert. Z.B. werden bei der Übertragung von MS zu Linux die aus zwei Codes bestehenden Zeilenumbrüche gegen den aus einem Code ersetzt.

    Ich würde an Deiner Stelle die Datei komplett einlesen in eine Bytefolge, also in einen "PHP-String", der aus Bytes besteht. Dann kannst Du auf jedes Element der Bytefolge (früher "String") direkt zugreifen.

    $buffer = file_get_contents($dateiname);
       echo $buffer[26];

    Oder du baust die Organisation gelich in einem PHP-Array auf. Zum Speichern kannst Du dieses Array dann serialisieren http://de2.php.net/manual/en/function.serialize.php und nach dem Wiederholen aus der Datei wieder in ein Array zurückverwandeln http://de2.php.net/manual/en/function.unserialize.php.

    Das funktioniert mit Dateien bis ca. 500kBytes in allen mir bisher bekannten Fällen sehr flott. Bei ca. 1MByte Dateigröße ist dann allerdings "Schluss mit Lustig" :-)

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Moin!

      PHP kennt allerdings gar keine reinen Textdateien mehr, sondern nur noch Dateien mit wahlfreiem Zugriff.

      Stimmt nicht. Die Funktion fopen() kennt z.B. einen Parameter "b" für "Binärdatei", fehlt dieser, dann wird das drunterliegende Betriebssystem "Textdatei" annehmen, wenn es diese Unterscheidung dort gibt. Bei Windows ist das der Fall, bei Unix nicht.

      Man kann zwar auch hier noch Dateien mit dem Öffnungsmodus 'a' (Append) öffnen, was einen dann daran hindert, mitten in die Datei hineinzuschreiben, aber zum Lesen kannst Du darin navigieren.

      Man konnte schon immer - auch bei Bändern - den Schreib/Lese-Zeiger auf jede beliebige Position innerhalb der Datei setzen, und dort dann mit Schreiben oder Lesen starten. Das ist alles nur eine Frage des Öffnungsmodus, und unabhängig von der verwendeten Sprache, also keine Spezialität von PHP, sondern die übliche Funktion des genutzten Betriebssystems.

      Allerdings: Modus "a" öffnet die Datei nur zum Schreiben, das Lesen dürfte da schwierig werden. Wie kommst du zu der Behauptung, man könne hierbei zum Lesen in der Datei navigieren?

      - Sven Rautenberg

      1. Hello,

        PHP kennt allerdings gar keine reinen Textdateien mehr, sondern nur noch Dateien mit wahlfreiem Zugriff.

        Stimmt nicht. Die Funktion fopen() kennt z.B. einen Parameter "b" für "Binärdatei", fehlt dieser, dann wird das drunterliegende Betriebssystem "Textdatei" annehmen, wenn es diese Unterscheidung dort gibt. Bei Windows ist das der Fall, bei Unix nicht.

        Stimmt nicht. Auch wenn kein 'b' gegeben wird, werden die Dateien nicht als reine Textdateien behandelt. Auch beim Openmode 'a' ist dies nicht der Fall. Man kann immer noch navigieren in der Datei (fseek), was bei echten Textdateien nicht der Fall wäre.

        PHP benutzt zum Öffnen der Datien immer den wahlfreien Modus (Blockmode). Alles andere wird bestenfalls emuliert.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Moin!

          PHP kennt allerdings gar keine reinen Textdateien mehr, sondern nur noch Dateien mit wahlfreiem Zugriff.

          Stimmt nicht. Die Funktion fopen() kennt z.B. einen Parameter "b" für "Binärdatei", fehlt dieser, dann wird das drunterliegende Betriebssystem "Textdatei" annehmen, wenn es diese Unterscheidung dort gibt. Bei Windows ist das der Fall, bei Unix nicht.

          Stimmt nicht. Auch wenn kein 'b' gegeben wird, werden die Dateien nicht als reine Textdateien behandelt. Auch beim Openmode 'a' ist dies nicht der Fall. Man kann immer noch navigieren in der Datei (fseek), was bei echten Textdateien nicht der Fall wäre.

          Welche API-Funktionen müsste PHP denn benutzen, um unter Windows, Linux oder Mac OS eine "echte Textdatei" zu öffnen. Sprich: Welches relevante Betriebssystem bietet denn noch Unterstützung für "echte Textdateieen" an?

          PHP benutzt zum Öffnen der Datien immer den wahlfreien Modus (Blockmode). Alles andere wird bestenfalls emuliert.

          Nun ja, um PHP geht's hier ja, und um alle damit erreichbaren Funktionen im Zusammenhang mit dem Dateizugriff. Welche Relevanz hat eine Exkursion in Rechnerverhalten, das heutzutage nirgendwo mehr anzutreffen ist?

          - Sven Rautenberg

  4. Alles klar :)

    danke für die ausführlichen Antworten!

    natürlich lag es am ASCII Übertragungsmodus. Habe .txt-Dateien jetzt aus dem ASCII-Filter geworfen.

    @ChrisB
    Kennen schon, aber wenn es schnell gehen muss, nehme ich halt was ich schon oft gemacht habe. file ist eine klasse Idee. Die anderen Möglichkeiten bringen mir nicht viel, weil ich die knapp 800 Nullen und Einsen nicht händisch in eine ini oder array Form bringen möchte.

    Gruß, Olli

    1. Moin!

      weil ich die knapp 800 Nullen und Einsen nicht händisch in eine ini oder array Form bringen möchte.

      Dabei gehst Du schon ziemlich umständlich vor.

      <?php  
      $var="1234567890";  
      for ($i=0; $i<strlen($var);$i++){  
       echo $i.': '.$var[$i]."<br />\n";  
      }  
      ?>
      

      das geht natürlich auch mit den Array-Elementen, die Du mit file eingelesen hast, denn

      <?php  
      $ar[0]='01';  
      $ar[1]='23'; // statt $ar=file('textdatei');  
      print $ar[1][0];  
      ?>
      

      liefert erwartungserfüllend eine 2.

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix