Datei zeilenweise einlesen

SY50

Level-1
Beiträge
271
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich weis dieses Thema gibt es hier schon öfter, aber leider konnte ich nirgends eine Lösung finden und die beschriebenen Bausteine "FileGets" usw. sind in meiner Version einfach nicht auffindbar.

Kann mir jemand vielleicht mittlerweile trotzdem bei meinem Problem helfen?

Also ich möchte mir gerne einen XML-Reader / Writer schreiben (Reader hat mehr Priorität).
Um eine XML einlesen zu können, würde ich allerdings dazu die Datei zeilenweise einlesen und behandeln.
Wie kann ich dies mit Standard 3S Bibliotheken ermöglichen? Also es gibt ja die SysFile Funktionen, welche aber immer gleich die ganze Datei in einen Buffer schreiben.
Ich möchte aber verhindern einen riesigen Buffer anlegen zu müssen.
=> Darum gerne zeilenweise einlesen der Daten.

Hat jemand ne Idee?

Danke schon mal
 
Da hier nichts kommt, gehe ich davon aus, dass es entweder nicht so einfach, oder komplett easy ist :).
keine ne Idee?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nimm die SysfileRead Funktion. Lege einen Puffer an, der eine Zeile auf jedenfall komplett beinhaltet. Also Zeile max 200 Zeichen dann Puffer 1000 Zeichen. Dann den gelesenen Puffer nach 13 und 10 durchsuchen bzw. $R$N. Den String bis zum Zeilenumbruch abspeichern und schon hast du die Zeile. Nun noch merken wo du angefangen hast zu lesen und an welcher Stelle $R$N war. Dann mit SysFileSetPos die Leseposition auf diese Pos setzen und wieder 1000 Bytes auslesen usw....

Nie die gesamte Datei einlesen und auswerten das ist zu viel je nach Größe.
 
Würdet Ihr den Buffer als String ausführen, oder als ARRAY OF Byte? Mit einem String Buffer könnte ich natürlich leichter nach Zeichen suchen und die Namen ausgeben.
Spricht irgendwas dafür / dagegen?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
dagegen: Ist die Zeile länger als 255 Zeichen gibts Probleme und du musst dir die LEN, LEFT, RIGHT, MID, FIND Funktionen für ein Bytearray schreiben

dafür: bist schneller am Ziel wenn du Zeilen <255 Zeichen hast
 
Hier die Funktionen die ich dazu nutze:

GLOBALE KONSTANTE:
CC_MAX_BUFFERINDEX: DWORD := 2047; (* maximum size of used string buffers *)

FIND ==> FindBA
Code:
FUNCTION FindBA : INT
(*
    This Function works like FIND. It can process ByteArrays with CC_MAX_BUFFERINDEX Bytes.


    string:s:='abcdef';     
    FindBA (ADR(s),'de'); => 4
    FindBA (ADR(s),'xy'); => 0
*)


VAR_INPUT
    pByteArray:POINTER TO ARRAY [0..CC_MAX_BUFFERINDEX] OF BYTE;        (* Byte array that will be searched through *)
    Length:WORD;    (*used length of the byte array*)
    Str1:STRING;    (*Search string*)
END_VAR
{library private}


VAR
    lengthStr1:INT;
    lengthDiff:INT;
    n1:INT;
    n2:INT;
    found:BOOL;
    pStr1:POINTER TO ARRAY [0..80] OF BYTE;
END_VAR

FindBA:=0;


pStr1:=ADR(Str1);


lengthStr1:=LEN(Str1);
lengthDiff:=Length-lengthStr1;


IF lengthdiff<0 THEN
    RETURN;
END_IF




FOR n1:=0 TO lengthDiff DO
    found:=TRUE;


    FOR n2:=0 TO lengthStr1-1 DO
        IF (pStr1^[n2] <>pByteArray^[n1+n2]) THEN
            found:=FALSE;
            EXIT;
        END_IF
    END_FOR


    IF found THEN
        FindBA:=n1+1;
        RETURN;
    END_IF


END_FOR

CONCAT ==> InsertBA
Code:
FUNCTION InsertBA : INT
(*
    This Function works like CONCAT. It can process ByteArrays with CC_MAX_BUFFERINDEX+1 Bytes.
    The return value is the Insert position plus the length of the insert string.
    In case of overflow => return value equals -1
*)


VAR_INPUT
    pByteArray:POINTER TO ARRAY [0..CC_MAX_BUFFERINDEX] OF BYTE; (*Byte array that will be used*)
    Str1:STRING;    (*The string that will be concatenated to the byte array*)
    Pos:INT;    (*Start position where the string sould be concatenated*)
END_VAR
{library private}


VAR
    i:INT;
    p_str1:POINTER TO ARRAY [0..80] OF BYTE;
END_VAR

p_str1:=ADR(Str1);


IF(Pos + LEN(Str1)) > (CC_MAX_BUFFERINDEX - TELNET_DELIM_LEN_SEND)
THEN
    InsertBA:= -1;
ELSE
    FOR i:=0 TO LEN(Str1) DO
        pByteArray^[Pos+i]:=p_str1^[i];
    END_FOR
    InsertBA:=Pos+LEN(Str1);
END_IF;


Aus Bytearray ein String machen,... geht natürlich nur bis 255 Zeichen
Code:
FUNCTION GetStringBA : STRING(255)
VAR_INPUT
	pByteArray		:POINTER TO ARRAY [0..CC_MAX_BUFFERINDEX] OF BYTE;		(* Byte array that will be searched through *)
	nLength			:WORD;	(*used length of the byte array*)
	nStart			:INT;	(* Startbyte *)
	nEnd			:INT; (* Endbyte *)
END_VAR
VAR
	pTemp		: POINTER TO BYTE;
	pByTemp 	: ARRAY [0..255] OF BYTE;
	strTemp		: POINTER TO STRING(255) ;


	i			: INT := 0;
END_VAR


pTemp := ADR(strTemp);


FOR i := nStart TO nEnd-2 DO


	pByTemp[i-nStart] := pByteArray^[i];
END_FOR;
pByTemp[i] := 0;
strTemp := ADR(pByTemp);


GetStringBA := strTemp^;
 
Zuletzt bearbeitet:
Du hast den Dateiinhalt im laufenden SPS-Betrieb geändert? Wenn du deine Strings nicht leerst bleibt der Inhalt erhalten. Steht in einem String "Hallo" und du schreibst nun "5" hinein, steht im String nicht "5", sondern "5allo".

Edit: Ich glaub ich hab dich falsch verstanden
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe jetzt alles mit einem Bytearray erledigt. Funktioniert ganz gut.
Ich kann auf verschiedene Zeichen reagieren und was dazwischen steht interessiert mich eigentlich nicht wirklich ;-)
 
so soll es sein,... gleich alles für Bytearray vorbereiten und später davon profitieren wenn es dann doch mal mehr als 255 bytes sind
 
Nimm die SysfileRead Funktion. Lege einen Puffer an, der eine Zeile auf jedenfall komplett beinhaltet. Also Zeile max 200 Zeichen dann Puffer 1000 Zeichen. Dann den gelesenen Puffer nach 13 und 10 durchsuchen bzw. $R$N. Den String bis zum Zeilenumbruch abspeichern und schon hast du die Zeile. Nun noch merken wo du angefangen hast zu lesen und an welcher Stelle $R$N war. Dann mit SysFileSetPos die Leseposition auf diese Pos setzen und wieder 1000 Bytes auslesen usw....

Nie die gesamte Datei einlesen und auswerten das ist zu viel je nach Größe.


Hallo zusammen,

habe das genau selben Problem, möchte von einer Großen Textdatei immer einzelne Zeilen einlesen und nicht die gesamte Datei.

Leider verstehe ich nicht wie man dieses SysFileSetPos einsetzt. Habe bisher lediglich die Datei per SysFileRead gelesen, aber dann halt im ganzen.

Kann mir da jemand etwas genauer erläutern wie die Zeileweise Lesefunktion geht?

Vielen Dank vorab, wäre für Hilfe sehr dankbar.
 
Zurück
Oben