Fread und Malloc

Aus Ethersex_Wiki
Wechseln zu: Navigation, Suche

! Dateien mit fread und malloc in den Speicher lesen Hier mal eine kleine Demonstration, wie man mit C Textdateien einlesen kann. Wie so oft, gibt's auch hier wieder zahllose Möglichkeiten:

  • Unterscheidung nach Standard
    • ANSI-C Funktionen fopen, fread, fwrite, fclose (sehr portabel)
    • POSIX Funktionen open, read, write, close (POSIX halt, sprich nur Unix-ähnliche Systeme, dafür schneller)
  • Unterscheidung nach Herangehensweise
    • Dateien Zeile für Zeile lesen und weiterverarbeiten
    • Dateien Block für Block (z.B. jeweils 4096 Zeichen) lesen und dann komplett im Arbeitsspeicher halten/bearbeiten (das ist übrigens für größere Dateien nicht zu empfehlen) :-)
fopen(NAME,TYP) Datei NAME öffnen, TYP r zum Lesen, w zum Schreiben
fread(BUF,BLOCKSIZE,COUNT,HANDLE) lese COUNT Blöcke der Größe BLOCKSIZE aus dem Dateihandle HANDLE und speichere in BUF. Rückgabe: Anzahl der gelesenen Blöcke
fwrite(BUF,BLOCKSIZE,COUNT,HANDLE) schreibe COUNT Blöcke der Größe BLOCKSIZE in das Dateihandle HANDLE und nehme die Daten aus dem Speicherbereich von BUF - Rückgabe: Anzahl der geschriebenen Blöcke
fclose(HANDLE) Schließe das Dateihandle HANDLE
  • Infos bezüglich realloc und free siehe ((CodingTutorialC-PrimGmp|hier))
  • wenn fopen die Datei nicht öffnen kann (weil sie zum Beispiel schlicht nicht existiert oder die Permissions nicht reichen), wird ein NULL-Pointer zurück gegeben. Dies sollte immer mit if oder ähnlichem kontrolliert werden.
/* Copyleft(C) 2005 Stefan Siegl <ssiegl@gmx.de>
 * no right reserved.
 *
 * example demonstrating use of fopen/fread in
 * conjunction with malloc/realloc
 */

#include <stdio.h>
#include <malloc.h>

static char *read_my_file(const char *filename);

int
main(void) 
{
  char *buffer = read_my_file("christian.txt");
  if(! buffer) {
    fprintf(stderr, "unable to read file, getting outta here\n");
    return 1;
  }

  printf("this is kinda expensive cat ...\n");
  printf("%s", buffer);

  /* get rid of allocated memory,
   * you mustn't use 'buffer' after that
   */
  free(buffer);

  return 0;
}

static char *
read_my_file(const char *filename) 
{
  char *buf = NULL;
  size_t alloc = 0;
  size_t len = 0;

  FILE *handle = fopen(filename, "r");
  if(! handle) return NULL; /* unable to open file */

  for(;;) {
    size_t read_bytes;

    if(len >= alloc) {
      /* we need more memory, allocate some ... */
      buf = realloc(buf, alloc = (alloc == 0 ? 4096 : alloc << 1));
      if(! buf) return NULL; /* unable to allocate memory */
    }

    /* call fread to read the next characters from our file handle,
     * named 'handle'. We request it to store to our buffer with
     * offset 'len' (the number of bytes we've already read).
     * We must not store more than 'alloc - len' bytes as we'd
     * write over the end of our allocated buffer then. */
    if((read_bytes = fread(buf + len, 1, alloc - len, handle)) <= 0)
      break; /* read until end of file (or error) */

    len += read_bytes;
  }

  fclose(handle); /* close file */

  buf = realloc(buf, len + 1); /* shrink buffer to the
                                * necessary size */
  if(! buf) return NULL;

  buf[len ++] = 0; /* terminate string */
  return buf;
}
  • obenstehenden Code bitte in fread.c abspeichern
  • gcc -o fread fread.c -Wall -W -ggdb -O ausführen
  • ./fread ausführen
  • eine Datei christian.txt anlegen
  • nochmal ausführen ^^
  • staunen :-)
  • Fragen hier ergänzen (-> FAQ)