Einteilung von Dateien Streams allgemeines Modell für bewegte Daten, wobei Daten (Bytes) zwischen dem Hauptspeicher und einer Quelle oder einem Ziel bewegt werden Quelle oder Ziel können sein Datenträger Hosts im Netzwerk lokale Schnittstellen (seriell, parallel, usb) Datenströme haben keine Struktur Daten, die mit einem Namen versehen auf einem Datenträger liegen, nennt man Dateien. Unterlegt man den Daten eine logische Struktur, so nennt man die einzelnen logischen Einheiten Datensätze.
Text/Binär Textdateien Bytes werden nach dem ASCII-Code interpretiert Oft zeilenweise organisiert Sonderbehandlung des Zeilenendes fgets, fputs Nahezu unbegrenzt portabel Binärdateien Bytes können beliebige Bedeutung haben Oft nicht portabel Dateiaufbau Dateien mit fester Datensatzlänge Dateien mit variabler Datensatzlänge Alle Datensätze haben den selben Aufbau Datensätze sind unterschiedlich lang Meistens Binärdaten Oft 1:1 abgelegte Strukturen Direkter Zugriff auf beliebige Datensätze ist möglich Oft nicht portabel fread, fwrite, fseek Dateiverarbeitung Textdateien haben oft variabel lange Datensätze, wenn man Zeilen als Datensätze betrachtet sequenzielle Verarbeitung, oder extra geführte Datensatzverwaltung (Index) High level I/O portabel gepuffert FILE-Pointer FILE* Low level I/O Eingeschränkt portabel Ungepuffert (u.u. langsam) Filehandle (int) Sehr systemnah
#include <stdio.h> #include <stdlib.h> #include <string.h> /*#include <process.h> */ typedef struct char vbez [25+1]; char vnr [12+1]; long Lbst; tart,tart; tart getart(file* pf,int i) tart tmp; fseek(pf,i*sizeof(tart),seek_set); fread(&tmp,sizeof (tart),1,pf); return tmp; void swap(file* pf,tart* A1, int i, tart* A2, int j) int x; tart tmp; x=fseek(pf,sizeof(tart)*j,seek_set); x=fwrite(a1,sizeof(tart),1,pf); x=fseek(pf,sizeof(tart)*i,seek_set); x=fwrite(a2,sizeof(tart),1,pf); tmp=*a1; *A1=*A2; *A2=tmp;
int main(int argc, char*argv[]) FILE *pf; long n; long *pindx; tart Art; /* Ausgabe */ if ((pf=fopen(argv[1],"r+b"))==null) exit (-1); while(fread(&art,sizeof(tart),1,pf)==1) printf("%-12s \"%-25s\" %6ld...", Art.vNr,Art.vBez,Art.Lbst); /* Sortierung */ int i,j; n= ftell(pf)/sizeof(tart); tart A1,A2; for (i=0,a1=getart(pf,i);i<n-1;++i,a1=getart(pf,i)) for (j=i+1,a2=getart(pf,j);j<n; ++j,a2=getart(pf,j)) if (strcmp(a1.vbez,a2.vbez)>0) swap(pf,&a1,i,&a2,j); rewind (pf); puts("===================================="); while(fread(&art,sizeof(tart),1,pf)==1) printf("%-12s \"%-25s\" %6ld...\n", Art.vNr,Art.vBez,Art.Lbst); fclose(pf); return 0; Bei sehr vielen Dateipositionierungen und Lese-/Schreibvorgängen an verschiedenen wahlfreien Positionen, wird die Pufferung der Daten unter Umständen eher zum Hindernis und zur Performancebremse.
Low Level I/O http://www.gnu.org/software/libc/manual/html_node/low_002dlevel-i_002fo.html http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_12.html#sec172 Öffen/Erzeugen und schließen von Dateien int open (const char *filename, int flags[, mode_t mode]) O_RDONLY: O_WRONLY: O_RDWR: O_APPEND: O_CREAT: O_EXCL: O_NOCTTY: O_NONBLOCK: O_TRUNC: Datei zum Lesen öffnen Datei zum Schreiben öffnen Datei zum Lesen und Schreiben öffnen Datei am Dateiende schreiben, unabh. Von der akt. Filepos. Datei erzeugen (wenn sie noch nicht existiert) Datei wird nur erzeugt, wenn sie noch nicht existiert wird in Verbindung mit O_CREAT verwendet Handelt es sich bei der Datei um ein Terminal (/dev/ttys0), so soll der Prozess nicht über dieses Terminal gesteuert werden open, read und write kehren sofort zurück, und haben ggf. 0 Bytes gelesen/geschrieben Datei wird beim Öffnen zum Lesen auf Länge 0 gelöscht int creat (const char *filename, mode_t mode) int close (int filedes) int dup (int oldfd) Lesen/Schreiben ssize_t read (int filedes, void *buffer, size_t size) ssize_t write (int filedes, const void *buffer, size_t size) Positionieren off_t lseek (int filedes, off_t offset, int whence) (SEEK_SET, SEEK_CUR, SEEK_END) int lseek (int fd,long offs, int whence) (L_SET, L_INCR, L_XTND)
Konvertierung FILE* <-> Deskriptor FILE * fdopen (int filedes, const char *opentype) int fileno (FILE *stream) Standarddeskriptoren STDIN_FILENO STDOUT_FILENO STDERR_FILENO 0 Standard Input 1 Standard Output 2 Standard Fehler Output
#include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #define F1 "Quellefile does not exist\n" #define F2 "Destination exists\n" /* Kopiert eine beliebige Datei ohne Beachtung der internen Struktur */ char vbuf[129]; int main(int argc, char**argv) int fd1,fd2,len,lenw=0; fd1=open(argv[1],o_rdonly); if (fd1>0) fd2=open(argv[2],o_creat O_WRONLY,0666); if (fd2>0) while ((len=read(fd1,vbuf,128))>0) write(1,vbuf,len); lenw=write(fd2,vbuf,len); if (lenw!=len)write(2,"mist\n",6); memset(vbuf,0,129); else write(2,f2,strlen(f2)); else write(2,f1,strlen(f1)); close(fd1); close(fd2); return 0;
/* Sortiert die Artikel in der Praktikumsartikeldatei */ /* A. Beck */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> typedef struct char vbez [25+1]; char vnr [12+1]; long Lbst; tart,tart; /******************************************************* liest einen Artikel von einer Dateiposition *******************************************************/ tart getart(int F, // Filedeskiptor int i) // Fileposition tart tmp; lseek(f,i*sizeof(tart),seek_set); read(f,&tmp,sizeof (tart)); return tmp; /******************************************************* vertauscht 2 Artikel in der Datei *******************************************************/ void swap(int F, // Filedeskiptor tart* A1, // Artikel 1 int i, // alte Pos. Art.1, neue Pos. Art.2 tart* A2, // Artikel 2 int j) // alte Pos. Art.1, neue Pos. Art.1 int x; tart tmp; x=lseek(f,sizeof(tart)*j,seek_set); x=write(f,a1,sizeof(tart)); x=lseek(f,sizeof(tart)*i,seek_set); x=write(f,a2,sizeof(tart)); tmp=*a1; *A1=*A2; *A2=tmp;
int main(int argc, char*argv[]) int F; long n; long *pindx; tart Art; /* Ausgabe */ if ((F=open(argv[1],O_RDWR))==-1) exit (-1); while(read(f,&art,sizeof(tart))==sizeof(tart)) printf("%-12s \"%-25s\" %6ld...\n", Art.vNr,Art.vBez,Art.Lbst); /* Sortierung */ int i,j; n= lseek(f,0,seek_end)/sizeof(tart); printf("n:%d\n",n); fgetc(stdin); tart A1,A2; for (i=0,a1=getart(f,i); i<n-1; i+=1,a1=getart(f,i)) for (j=i+1,a2=getart(f,j);j<n ; j+=1,a2=getart(f,j)) if (strcmp(a1.vbez,a2.vbez)>0) swap(f,&a1,i,&a2,j); lseek (F,0,SEEK_SET); puts("===================================="); while(read(f,&art,sizeof(tart))==sizeof(tart)) printf("%-12s \"%-25s\" %6ld...\n", Art.vNr,Art.vBez,Art.Lbst); close(f); return 0;
Nachfolgendes Beispiel stellt eine serielle Verbindung zu einem Mikroprozessor her. Dieser sendet über die serielle Schnittstelle im Sekundentakt Strings, die eine gemessene Temperatur und die ID des Sensors übermittelt beck@pc:beck/avr/ds1820_2>./a.out ID: 104522010108004CHex: 0008 T= 4.0 ID: 1062012401080038Hex: 002E T= 22.0 ID: 104522010108004CHex: 0008 T= 4.0 ID: 1062012401080038Hex: 002E T= 21.5 # Der so genannte kanonische Modus: Hier erfolgt das Lesen und Schreiben zeilenorientiert. Das heißt, eine Eingabe wird erst weitergereicht, wenn ein Zeilenabschluss (Linefeed, NL) oder Carriage Return (CR) übertragen wurde. Für diesen Modus benötigt man die Steuerzeichen des c_cc-arrays der termios-struktur. Der Nachteil ist, dass ein Programm beim Lesen in diesem Modus so lange wartet (CPU-Zeit vergeudet), bis tatsächlich eine Zeile übertragen wurde. Wird kein Zeilenabschluss gelesen, so wird für immer gewartet. Die Aufgabe des Zwischenspeicherns übernimmt der Kernel in speziellen Puffern. Es gibt einen Eingabe- und einen Ausgabepuffer. Steuerzeichen regeln, wann welche Puffer entleert werden und somit ihren Inhalt an das Gerät oder das Programm weitergeben. # Beim nicht kanonischen Modus erfolgt das Lesen oder Schreiben entweder nach einer bestimmte Anzahl an Bytes (was auch nur ein Byte und somit ein Zeichen sein kann) oder es kann eine gewisse Zeit dafür angegeben werden. Hierfür können folgende zwei Felder des Arrays c_cc gesetzt werden. In c_cc[vtime] wird die entsprechende Zeit in Zehntelsekunden und in c_cc[vmin] das Minimum der zu lesenden Bytes angegeben. (http://www.pronix.de/pronix-379.html)
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define BAUDRATE B19200 #define MODEMDEVICE "/dev/ttys1" int fd; unsigned char receive() int res=0,i; char buffer[128]=""; while (1) res = read(fd,buffer,127); if (res!=-1)break; usleep (10); if (res)write(1,buffer,res); int main(int argc, char**argv) struct termios newtio=; // man 2 open, man termios fd=open(modemdevice, O_RDONLY O_NOCTTY O_NDELAY ); if (fd <0)printf("Fehler ttys1"); exit(0); // Control flag 8bit/char, kein Modem, (8N1) newtio.c_cflag = BAUDRATE CS8 CLOCAL CREAD; // Inputflag ignore Errors newtio.c_iflag = IGNPAR; // Outptflag newtio.c_oflag = 0; // Localflag kein echo, keine spez.steuerzeichen newtio.c_lflag = 0; // Steuerzeichen newtio.c_cc[vtime]= 0;// ohne timer newtio.c_cc[vmin] = 1;// blockt bis 1 char empfangen tcflush(fd, TCIFLUSH); tcsetattr(fd,tcsanow,&newtio); while (1) receive();