csv schreiben mit Zeilenumbruch

Ampel03

Level-1
Beiträge
45
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich schreibe in einer file einen alaogen Wert mit. Der Wert wird vor dem Schreiben in die csv datei mit Uhrzeit und Einheit in einem String gesetzt (concat). Am Ende des Strings wird ein Zeilenumbruch in Form von "$n" concatiert.

Alle paar Sekunden wir nun der String in die Datei hinzugefügt. Und da ein Zeilenumbruch drin steht, wird Zeile für Zeile geschrieben. Funktioniert auch alles soweit.

Nur manchmal passiert es, dass der Zeilenumbruch eines Strings nicht mit "übertragen" wird und zwei Zeilen somit in einer Zeile stehen. Es ist keine Regelmäßigkeit, sondern nur unregelmäßig. Habe mir die csv im Editor angeschaut, da fehlt wirklich ab und an der Zeilenumbruch. In Excel sieht man es noch deutlicher.

Ist vielleicht das Zeichen "$n" nicht richtig? Gibt es andere, die eingesetzt werden könnten?

Da das ganze ja recht gut funktioniert, glaube ich nicht, dass es am Code zum Schreiben in die Datei liegt, sondern eher am Bilden des Reinschreibstrings.
Hier der Code zum Erstellen des Strings:
FUNCTION_BLOCK A30_Aussentemp_in_String
VAR_INPUT
rAussentemp : REAL;
sEinheit : STRING;
uHour : UINT;
uMinute : UINT;
uSeconds : UINT;
END_VAR
VAR_OUTPUT
sStringausgabe : STRING;
END_VAR
VAR
sHour : STRING;
sMinute : STRING;
sSeconds : STRING;
END_VAR

(* Dieser FB generiert aus Variabel und Zeit einen fertigen String zum Schreiben in eine Datei: *)
(* "Stunde:Minute:Sekunde Einheit Temperatur" *)
sHour := CONCAT(UINT_TO_STRING(uHour),':'); (* Stunde zum String machen und dabei sofort ein Doppelpunkt als Trennzeichen dahintersetzen *)
sMinute := CONCAT(UINT_TO_STRING(uMinute),':'); (* Minute zum String machen und dabei sofort ein Doppelpunkt als Trennzeichen dahintersetzen *)
sSeconds := CONCAT(UINT_TO_STRING(uSeconds),';'); (* Sekunde zum String machen und dabei sofort ein Leerzeichen als Trennzeichen dahintersetzen *)
sEinheit := CONCAT(sEinheit,';'); (* Leerzeichen vor der Einheit einfügen *)
IF (uHour < 10 AND uHour >= 0) THEN (* wenn die Stunde nur einstellig ist, dann zweistellig machen *)
sHour := CONCAT('0',sHour);
END_IF;

IF (uMinute < 10 AND uMinute >= 0) THEN (* wenn die Minute nur einstellig ist, dann zweistellig machen *)
sMinute := CONCAT('0',sMinute);
END_IF;

IF (uSeconds < 10 AND uSeconds >= 0) THEN (* wenn die Sekunde nur einstellig ist, dann zweistellig machen *)
sSeconds := CONCAT('0',sSeconds);
END_IF;
sStringausgabe := CONCAT(sHour,sMinute); (* jetzt alles schön nacheinander reinschreiben *)
sStringausgabe := CONCAT(sStringausgabe,sSeconds);
sStringausgabe := CONCAT(sStringausgabe,sEinheit);
sStringausgabe := CONCAT(sStringausgabe,REAL_TO_STRING(rAussentemp));
sStringausgabe := CONCAT(sStringausgabe,'$n'); (* zum Schluss noch ein Zeilenumbruch einfügen. *)


Hat jemand Grundideen, wo ich suchen sollte?

Ampel03
 
Hallo Ampel03,
dein Code ist richtig und dein Problem liegt wahrscheinlich wirklich am '$n'.
Laut Codesys-Hilfe heisst $n - neue Zeile und $r - Zeilenumbruch.

Keine Ahnung, was der Unterschied ist. Eventuell hat das was mit der Zeilenlänge zu tun.

Wenn $n feststellt, dass der neue String noch in die alte Zeile passt, macht er eben keinen Zeilenumbruch.
$r macht dagegen immer den Zeilenumbruch. :p
Ist nur eine Vermutung, aber würde ich mal versuchen.
Schönes Wochenende
eNDe
 
$l$n

Probier mal '$r$n' das macht man in anderen Hoch-Sprachen auch so. In VB gibt es zB. die Konstante vbCrLf (visual basic carrage return line feed)

Ich habe so etwas im Prinzip auch schon gemacht, ich sende Diagnose Strings an ein Terminal und benötige ebenfalls den Zeilenumbruch.


iLen := LEN (theMessage);
IF ((iLen < (TXBUFFLEN -5)) (* no buffer overrun allowed *)
AND (theImage.diagPort.bLogging = FALSE) (* actually sending ASCII data *)
AND (theImage.diagPort.iCommand = T_ENABLE) (* no string to send actually *)
AND (theImage.diagPort.iRes = 0)) THEN (* and no resting bytes in buffer *)
theMessage := CONCAT (theMessage, '$L$N');
theImage.diagPort.iCommand := T_PUTDATA;
iIndex:= 0;
pText := ADR (theMessage);
iLen := LEN (theMessage);
WHILE (iIndex <= iLen) DO
theImage.diagPort.tSend[iIndex] := pText^;
pText := pText+1;
iIndex := iIndex+1;
END_WHILE
theImage.diagPort.iLen := iLen;
END_IF

Ich habe aber $L$N als neue Zeile in meinem Source. (sorry aber beim Kopieren ist die Formatierung des Source verloren gegangen)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi, ich vermute du verwendest Windows und unter Windows ist es Standard das ein absichtlicher Zeilenumbruch (Enter) mit den Ascii-Zeichen 13 und 10 codiert ist.

13 = Cr (Carriage Return) = Wagen zurück
10 = Lf (Line feed) = Zeilenumbruch
(die Kombination von beidem ist ein Relikt aus der Zeit der Schreibmaschinen)

Wenn du zum Beispiel eine CSV Datei mit Excel erstellst und diese dann in CoDeSys ausliest, wirst du sehen das am Ende jeder Zeile '$R$N'. Wenn '$R' allein funktioniert, liegt das vermutlich daran das es nicht ganz so streng genommen wird und ebenso erkannt wird. Ich würde daher empfehlen immer '$R$N' zu verwenden um Fehler zu vermeiden.

mfg altelulex
 
Zurück
Oben