mikrocontroller.net

Forum: PC-Programmierung Kontinuierlich in eine Datei schreiben


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von baer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Leut,

ich möchte mit einem kleinen C Programm kontinuierlich in eine Datei 
schreien (nur schreiben, da ein anderes Programm kontinuierlich lesen 
soll).

vom Prinzip soll das so aufgebaut werden
FILE * pFile;
pFile = fopen ("tmp.ad","w+");
if (pFile!=NULL){
  while(1){

    char * data = "test"

    fwrite( data, sizeof(data), 1, pFile );
    
    usleep(1000000) //sleep 1 second
  }
}
fclose ( pFile );

aber 1. stimmt da was nicht, weshalb er die datei zwar erzeugt aber 
nichts reinschreibt...
2. soweit ich weiß, würde er dann einfach drauf losschreiben und mir die 
datei nach und nach befüllen... soll aber eigentlich nur den Inhalt 
"ersetzen".

als letztes Problem habe ich noch (neues kurzes thema):
mit dem befehl read_val(params) bekomme ich ein 'double' zurück...
wie kann ich das "verwurschteln" das ich dies dann als char 
weiterverarbeiten kann und dann in die datei schreiben kann?

ziel ist es das es etwa so aussieht:
char * data = "anfang" & read_val(params) & "ende";

vielen dank für die Hilfe

& evtl. kann mir mal jemand sagen wie ich C-Code hier richtig 
deklariere...

: Verschoben durch Admin
von baer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Problem N konnte ich so lösen:
snprintf(buffer, sizeof(buffer), "(%g, %g)", read_val(parm), 
read_val(parm));

jetzt stellt sich nur noch die Frage wie ich "buffer" in die Daten 
kontinuierlich schreiben kann ohne die Datei jedes mal neu zu öffnen!

von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mit rewind.

Grüsse,
René

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
baer schrieb:
> char * data = "test"
>
>     fwrite( data, sizeof(data), 1, pFile );

Was gibt hier der sizeof-Operator zurück?

von baer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
yes man

das ist schonmal geil und funktioniert FAST wie ich will...

leider schreibt er in meine Datei:
[ 622, 0, 0, 0, 0, 0, 0, 0 ]  óv                            „óv|óvLóv\óvdóv            lóvtóv        Dóv        œóv¤óv¬óvŒóv        ”óv                                                ¼óv´óv    Ìóv                                    Äóv   

das zwischen den klammern [] ist Korrekt...
alles was folgt kann ich mir nicht erklären woher das kommt!?
char buffer[256]; 
snprintf(buffer, sizeof(buffer), 
  "[ %g, %g, %g, %g, %g, %g, %g, %g ]", 
  read_val(0x68,1, 12, 1, 1), 
  read_val(0x68,2, 12, 1, 1),
  read_val(0x68,3, 12, 1, 1),
  read_val(0x68,4, 12, 1, 1),
  read_val(0x69,1, 12, 1, 1),
  read_val(0x69,2, 12, 1, 1),
  read_val(0x69,3, 12, 1, 1),
  read_val(0x69,4, 12, 1, 1)
);

rewind( pFile );
fwrite ( buffer, sizeof(buffer), 1, pFile );


von baer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> baer schrieb:
>> char * data = "test"
>>
>>     fwrite( data, sizeof(data), 1, pFile );
>
> Was gibt hier der sizeof-Operator zurück?

vermutlich "kacke" :D ...
hab das auch nur kopiert. Ist das Falsch???
was muss hier hin?

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
baer schrieb:
> Ist das Falsch???
> was muss hier hin?

Was willst Du hier bestimmen? Die Größe des Pointers "data" oder die 
Länge des Strings, auf den der Pointer zeigt?

Wenn Du fwrite verwendest, kannst Du auch fprintf nutzen ...

von Moe S. (loetsinn)


Bewertung
0 lesenswert
nicht lesenswert
Außer, was Rufus schon sagte:

Wenn Du Dateien mit fopen statt mit open öffnest, benutzt stdio einen 
Buffer. Den kannst du mit fflush(pFile) committen. Möglicherweise sieht 
es deshalb so aus, als wäre die Datei leer, obwohl du sie beschreibst.

Du solltest außerdem wirklich den Returncode von snprintf testen! Wenn 
der Buffer nicht groß genug ist, kann das zu "Müll" im Output führen...

von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vor dem snprintf Buffer Initialisieren mit memset(buffer, 0, 
sizeof(buffer))

Grüsse,
René

von Daniel A. (daniel-a)


Bewertung
0 lesenswert
nicht lesenswert
Rene H. schrieb:
> Vor dem snprintf Buffer Initialisieren mit memset(buffer, 0,
> sizeof(buffer))

Nö, dann werden nullbytes geschrieben. besser size_t s = snprintf( und 
spater s stat sizeof(data)

Oder gleich fprintf verwenden, oder strlen.

PS: Wäre ein FIFO statt ein File hier nicht besser?

: Bearbeitet durch User
von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Rene H. schrieb:
>> Vor dem snprintf Buffer Initialisieren mit memset(buffer, 0,
>> sizeof(buffer))
>
> Nö, dann werden nullbytes geschrieben. besser size_t s = snprintf( und
> spater s stat sizeof(data)

Nö, das funktioniert nur solange der String gleich gross oder grösser 
wird.

Grüsse,
René

von baer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> PS: Wäre ein FIFO statt ein File hier nicht besser?

ha... genau das Problem mit dem wenn der "String" die länge ändert habe 
ich jetzt...

FIFO klingt (nach kurzen Googeln) super, und genau nachdem was ich 
suche...
> evtl n kurzes how to?

Danke

von Manfred (Gast)


Bewertung
0 lesenswert
nicht lesenswert
baer schrieb:
> ich möchte mit einem kleinen C Programm kontinuierlich in eine Datei
> schreien (nur schreiben, da ein anderes Programm kontinuierlich lesen
> soll).

Bekommst Du die beiden Jobs Schreiben und Lesen synchronisiert? Wenn 
nicht, kassierst Du sporadische Zugriffsfehler, weil vom Schreibprozess 
gerade geöffnet.

von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> PS: Wäre ein FIFO statt ein File hier nicht besser?

Auch nein, FIFO löst das grössen Problem in einem File nicht. Das 
Problem ist das File, nicht wie es da reinkommt.

Grüsse,
René

von Daniel A. (daniel-a)


Bewertung
0 lesenswert
nicht lesenswert
Ein FIFO ist kein gewöhnliches file, sondern ein spezielles first in 
first out file. Ein Programm kann nicht reinschreiben solange keins 
davon liest, und ein Programm kann nicht davon Lesen solange keins 
schreibt. Ein Fifo file verbraucht auf der HDD keinen Speicherplatz.

Ein normales file wäre auf jeden fall Murks. Eigentlich gibt es fast nie 
einen grund kontinuierlich Daten zu schreiben, die eventuell nicht 
gelesen werden. Sollten wirklich sich kontinuierlich verändernde Werte 
in mehreren Programmen verfügbar sein, währe eventuell shared memory in 
Kombination mit c11 atomics + volatile eine gute methode. Andernfalls 
würde ich raten eine Library zu schreiben um die Werte abzufragen, wenn 
diese tatsächlich benötigt werden, z.B. mit hillfe von sockets, oder 
durch verwenden einer bestehenden Message queue library. Oder man nutzt 
dbus.

Zusammengefasst, löse es irgendwie, aber besser nicht so wie jetzt.

PS: Sobald man rewind oder fseek im Programm hat, macht man meist was 
falsch oder zumindest nicht ideal.

: Bearbeitet durch User
von oszi40 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> löse es irgendwie, aber besser nicht so wie jetzt.

Mach öfter eine neue Datei auf und schmeiß die alten nach dem lesen weg? 
Zu lange/große Datei macht selten glücklich (Zeitproblem bei einigen 
GB).

von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Ein FIFO ist kein gewöhnliches file, sondern ein spezielles first in
> first out file. Ein Programm kann nicht reinschreiben solange keins
> davon liest, und ein Programm kann nicht davon Lesen solange keins
> schreibt. Ein Fifo file verbraucht auf der HDD keinen Speicherplatz.
>
> Ein normales file wäre auf jeden fall Murks. Eigentlich gibt es fast nie
> einen grund kontinuierlich Daten zu schreiben, die eventuell nicht
> gelesen werden. Sollten wirklich sich kontinuierlich verändernde Werte
> in mehreren Programmen verfügbar sein, währe eventuell shared memory in
> Kombination mit c11 atomics + volatile eine gute methode. Andernfalls
> würde ich raten eine Library zu schreiben um die Werte abzufragen, wenn
> diese tatsächlich benötigt werden, z.B. mit hillfe von sockets, oder
> durch verwenden einer bestehenden Message queue library. Oder man nutzt
> dbus.
>
> Zusammengefasst, löse es irgendwie, aber besser nicht so wie jetzt.
>
> PS: Sobald man rewind oder fseek im Programm hat, macht man meist was
> falsch oder zumindest nicht ideal.

Natürlich. Aber das löst das Problem nicht.

Grüsse,
René

von Daniel A. (daniel-a)


Bewertung
0 lesenswert
nicht lesenswert
Dann verstehe ich das Problem nicht. Gibt es einen Grund, warum du in 
wiederholt in ein File schreiben musst, oder brauchst du ein 
Minimalbeispiel zu einer der vorgeschlagenen Möglichkeiten, oder was ist 
es? Was ist das Ziel der ganzen Übung?

von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Dann verstehe ich das Problem nicht. Gibt es einen Grund,

Ich vermute er will lediglich aktuelle Messdaten sicherstellen.
Aber so ganz klar ist mir die Intention auch nicht.

Grüsse,
René

von Axel S. (a-za-z0-9)


Bewertung
0 lesenswert
nicht lesenswert
Rene H. schrieb:
> Daniel A. schrieb:
>> PS: Wäre ein FIFO statt ein File hier nicht besser?
>
> Auch nein, FIFO löst das grössen Problem in einem File nicht.

Was ist "das grössen Problem in einem File"?

Das ergibt ja schon orthografisch gar keinen Sinn. und auch sonst nicht 
so wirklich. Um zwei Prozesse miteinander kommunizieren zu lassen, sind 
Files fast nie die Lösung. FIFOs schon eher. Aber ohne Details des 
Problems zu kennen, können wir über die Lösung nur raten.

man 5 ipc

von Rene H. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Axel S. schrieb:
> Rene H. schrieb:
>> Daniel A. schrieb:
>>> PS: Wäre ein FIFO statt ein File hier nicht besser?
>>
>> Auch nein, FIFO löst das grössen Problem in einem File nicht.
>
> Was ist "das grössen Problem in einem File"?
>
> Das ergibt ja schon orthografisch gar keinen Sinn. und auch sonst nicht
> so wirklich. Um zwei Prozesse miteinander kommunizieren zu lassen, sind
> Files fast nie die Lösung. FIFOs schon eher. Aber ohne Details des
> Problems zu kennen, können wir über die Lösung nur raten.
>
> man 5 ipc
Mein Fehler, ich hatte in der Tat das mit dem zweiten Prozess übersehen.
Dann ist FIFO sicher eine Alternative.

Grüsse,
René

von baer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
nun ja,
ich habe wie schon erraten messdaten (aktuell. 5 adcs die stromwerte von 
z.b. kühlschrank, waschmaschine, licht... abrufen)
diese rufen gleichzeitig etwa 10 prozesse live (halt eben mit 
minimalster verzögerung) ab (also diverse "monitore")...
da ich aber die i2c schnittstelle nicht überlasten will, cache ich die 
daten und lese nur den cache!

die obigen lösungen funktionieren aber nicht ganz ohne haken... groß 
wird die datei nicht, da ich alle daten wieder überschreibe!

=> sichern in eine db folgt noch, aber da brauch ich weit aus weniger 
daten (5 minutentakt) und das macht mein .c in ferner Zukunft selbst...

fifo klingt echt spannend... aber ich habe keinen echten "ansatz"...
besonders hakt es hier sicherlich wie ich die daten dann zurück in php 
bekomme... aber auch hier wäre vermutlich n kleines .c kein problem das 
ich über exec aufrufe!

nun wo lade ich meine daten ab => speicher statt datei
und wie komme ich da wieder ran...

ein kleines how to wäre echt nett...

danke für die konstruktiven gedanken die ihr mit mir teilt!

von Daniel A. (daniel-a)


Bewertung
0 lesenswert
nicht lesenswert
Bei einem FIFO können geschriebene Daten aber nur einmal gelesen werden, 
selbst wenn mehrere Prozesse darauf lesend zugreifen bekommt nur einer 
die Daten. Für diesen Anwendungsfall währe es damit wohl ungeeignet.

von Pit (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Axel S. schrieb:
> Um zwei Prozesse miteinander kommunizieren zu lassen, sind
> Files fast nie die Lösung.

Das seh ich anders. Files sind GENAU die Lösung. Und zwar 'memory 
mapped'.

Schau mal bei Google nach 'memory mapped files'. Da wird Dir geholfen.

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
baer schrieb:
> sichern in eine db folgt noch, aber da brauch ich weit aus weniger daten
> (5 minutentakt) und das macht mein .c in ferner Zukunft selbst...

Du kannst auch Deine aktuellen Daten in einer Datenbank speichern. Im 
Arbeitsspeicher; sieh Dir mal SQLite an. Das kann das, und das macht das 
mit vorzüglicher Performance, und ist in reinem C geschrieben.

Und für die Langzeitarchivierung kannst Du das auch nehmen, SQLite kann 
selbstverständlich auch mit Dateien arbeiten.

von Sven B. (scummos)


Bewertung
0 lesenswert
nicht lesenswert
Vielleicht bin ich ein Hipster, aber ich würd' dbus nehmen. Die eine 
Anwendung emittiert ein Signal, die anderen hören darauf und gut ist. 
Die meisten anderen Lösungen sind "ich bau mir mein eigenes IPC nur 
schlechter als dbus".

: Bearbeitet durch User
von neuer PIC Freund (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hilft
   ...
   fwrite( data, sizeof(data), 1, pFile );
   fsync(pFile);
   ...
auf deinem System?

von tictactoe (Gast)


Bewertung
1 lesenswert
nicht lesenswert
baer schrieb:
> Problem N konnte ich so lösen:
> snprintf(buffer, sizeof(buffer), "(%g, %g)", read_val(parm),
> read_val(parm));

Falls das funktioniert, dann nur zufällig! Ich nehme mal an, dass 
read_val() von irgenwoher seriell einliest. Es gibt aber keine Garantie, 
dass das erste read_val(parm) in dieser Zeile vor dem zweiten 
read_val(parm) aufgerufen wird. Das kann mal so, mal andersrum 
geschehen.

Die richtige Lösung lautet daher:
double p1 = read_val(parm);
double p2 = read_val(parm);
snprintf(buffer, sizeof(buffer), "(%g, %g)", p1, p2);

von Moe S. (loetsinn)


Bewertung
2 lesenswert
nicht lesenswert
Also, so wie sich das ganze jetzt anhört, fällt die Anwendung in das 
Publish/Subscribe-Pattern: 
https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern.
Eine Quelle (Publisher) von Daten, mehrere Subscriber, die diese Daten 
erhalten wollen. Für diese Anwendung gibt es bereits fertige, erprobte 
Lösungen, DBus und Redis z.B.
Warum nicht was fertiges nehmen?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.